[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [POWERPC][XEN] Set up an RTAS node for dom0 and proxy methods



# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Date 1181074198 14400
# Node ID 6750b1320159458c15fed78ba26d202ada818e57
# Parent  06a32f040d64a9e26d29f97bd0c48cf25724788a
[POWERPC][XEN] Set up an RTAS node for dom0 and proxy methods

If real FW supplies an RTAS layer then pass thru the methods Xen will
proxy for Dom0.
 - NVRAM read/write methods work, see  nvsetenv(8) or nvram(8).
 - Firmware flash methods exist, but currently "chicken switched" off
   for further testing.

Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
---
 xen/arch/powerpc/Makefile     |    2 
 xen/arch/powerpc/ofd_fixup.c  |   37 +-------
 xen/arch/powerpc/oftree.h     |    4 
 xen/arch/powerpc/rtas.c       |  151 ++++++++++++++++++++++++++++------
 xen/arch/powerpc/rtas.h       |   31 +++++++
 xen/arch/powerpc/rtas_flash.c |  182 ++++++++++++++++++++++++++++++++++++++++++
 xen/arch/powerpc/rtas_nvram.c |  129 +++++++++++++++++++++++++++++
 7 files changed, 477 insertions(+), 59 deletions(-)

diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/Makefile
--- a/xen/arch/powerpc/Makefile Sun Jun 03 10:39:31 2007 -0400
+++ b/xen/arch/powerpc/Makefile Tue Jun 05 16:09:58 2007 -0400
@@ -35,6 +35,8 @@ obj-y += physdev.o
 obj-y += physdev.o
 obj-y += platform.o
 obj-y += rtas.o
+obj-y += rtas_nvram.o
+obj-y += rtas_flash.o
 obj-y += setup.o
 obj-y += shadow.o
 obj-y += smp.o
diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/ofd_fixup.c
--- a/xen/arch/powerpc/ofd_fixup.c      Sun Jun 03 10:39:31 2007 -0400
+++ b/xen/arch/powerpc/ofd_fixup.c      Tue Jun 05 16:09:58 2007 -0400
@@ -26,8 +26,6 @@
 #include "of-devtree.h"
 #include "oftree.h"
 #include "rtas.h"
-
-#undef RTAS
 
 ofdn_t ofd_boot_cpu;
 
@@ -307,26 +305,6 @@ static ofdn_t ofd_chosen_props(void *m, 
     return n;
 }
 
-#ifdef RTAS
-static ofdn_t ofd_rtas_props(void *m)
-{
-    static const char path[] = "/rtas";
-    static const char hypertas[] = "dummy";
-    ofdn_t p;
-    ofdn_t n;
-
-    /* just enough to make linux think its on LPAR */
-
-    p = ofd_node_find(m, "/");
-
-    n = ofd_node_add(m, p, path, sizeof(path));
-    ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
-    ofd_prop_add(m, n, "ibm,hypertas-functions", hypertas, sizeof (hypertas));
-
-    return n;
-}
-#endif
-
 static ofdn_t ofd_xen_props(void *m, struct domain *d, ulong shared_info)
 {
     ofdn_t n;
@@ -382,8 +360,8 @@ static ofdn_t ofd_xen_props(void *m, str
     return n;
 }
 
-int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
-                   ulong shared_info)
+ulong ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
+                     ulong shared_info)
 {
     void *m;
     const ofdn_t n = OFD_ROOT;
@@ -423,11 +401,8 @@ int ofd_dom0_fixup(struct domain *d, ulo
     printk("Remove original /rtas\n");
     ofd_prune_path(m, "/rtas");
 
-#ifdef RTAS
-    printk("Create a new RTAS with just enough stuff to convince "
-           "Linux that its on LPAR\n");
-    ofd_rtas_props(m);
-#endif
+    rtas_proxy_init(m);
+
 #ifdef FIX_COMPAT 
     const char compat[] = "Hypervisor,Maple";
     r = ofd_prop_add(m, n, "compatible", compat, sizeof (compat));
@@ -446,5 +421,5 @@ int ofd_dom0_fixup(struct domain *d, ulo
 #ifdef DEBUG
     ofd_walk(m, __func__, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
 #endif
-    return 1;
-}
+    return ofd_size(m);
+}
diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/oftree.h
--- a/xen/arch/powerpc/oftree.h Sun Jun 03 10:39:31 2007 -0400
+++ b/xen/arch/powerpc/oftree.h Tue Jun 05 16:09:58 2007 -0400
@@ -28,8 +28,8 @@ extern ulong oftree_end;
 extern ulong oftree_end;
 extern ofdn_t ofd_boot_cpu;
 
-extern int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
-                          ulong shared_info);
+extern ulong ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
+                            ulong shared_info);
 extern void ofd_memory_props(void *m, struct domain *d);
 
 extern int firmware_image_start[0];
diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/rtas.c
--- a/xen/arch/powerpc/rtas.c   Sun Jun 03 10:39:31 2007 -0400
+++ b/xen/arch/powerpc/rtas.c   Tue Jun 05 16:09:58 2007 -0400
@@ -13,7 +13,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2006
+ * Copyright (C) IBM Corp. 2006, 2007
  *
  * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
  */
@@ -22,24 +22,16 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/errno.h>
+#include <xen/sched.h>
 #include "of-devtree.h"
 #include "rtas.h"
 
-static int rtas_halt_token = -1;
-static int rtas_reboot_token = -1;
 int rtas_entry;
 unsigned long rtas_msr;
 unsigned long rtas_base;
 unsigned long rtas_end;
 
-struct rtas_args {
-    int ra_token;
-    int ra_nargs;
-    int ra_nrets;
-    int ra_args[10];
-} __attribute__ ((aligned(8)));
-
-static int rtas_call(struct rtas_args *r)
+int rtas_call(void *r)
 {
     if (rtas_entry == 0)
         return -ENOSYS;
@@ -47,11 +39,51 @@ static int rtas_call(struct rtas_args *r
     return prom_call(r, rtas_base, rtas_entry, rtas_msr);
 }
 
+/* rtas always uses physical address */
+void *rtas_remote_addr(ulong addr, ulong length)
+{
+    struct vcpu *v = get_current();
+    struct domain *d = v->domain;
+    ulong mfn;
+    ulong mfn_end;
+
+    mfn = gmfn_to_mfn(d, addr >> PAGE_SHIFT);
+    if (mfn == INVALID_MFN)
+        return NULL;
+
+    /* a little paranoid since almost everyone will pass us page
+     * bounded thingies, but just in case */
+    mfn_end = gmfn_to_mfn(d, (addr + length) >> PAGE_SHIFT);
+    if (mfn_end == INVALID_MFN)
+        return NULL;
+
+    return (void *)((mfn << PAGE_SHIFT) | (addr & (PAGE_SIZE - 1)));
+}
+
+/* these do not proxy */
+#define RTAS_HALT 0
+#define RTAS_REBOOT 1
+
+struct rtas_token rt_power_off = { .name = "power-off", .token = -1, };
+struct rtas_token rt_system_reboot = { .name = "system-reboot", .token = -1};
+
+static struct rtas_token *tokens[] = {
+    /* these do not proxy */
+    [RTAS_HALT] = &rt_power_off,
+    [RTAS_REBOOT] = &rt_system_reboot,
+    &rt_nvram_store,
+    &rt_nvram_fetch,
+    &rt_manage_flash,
+    &rt_validate_flash,
+    &rt_update_reboot_flash
+};
+
+static int rtas_proxy;
+
 int __init rtas_init(void *m)
 {
-    static const char halt[] = "power-off";
-    static const char reboot[] = "system-reboot";
     ofdn_t n;
+    int i;
 
     if (rtas_entry == 0)
         return -ENOSYS;
@@ -60,22 +92,87 @@ int __init rtas_init(void *m)
     if (n <= 0)
         return -ENOSYS;
 
-    ofd_getprop(m, n, halt,
-                &rtas_halt_token, sizeof (rtas_halt_token));
-    ofd_getprop(m, n, reboot,
-                &rtas_reboot_token, sizeof (rtas_reboot_token));
+    for (i = 0; i < ARRAY_SIZE(tokens); i++) {
+        ofd_getprop(m, n, tokens[i]->name,
+                    &tokens[i]->token, sizeof (tokens[i]->token));
+        if (!rtas_proxy && tokens[i]->proxy && tokens[i]->token != -1)
+            rtas_proxy = 1;
+    }
     return 1;
+}
+
+int rtas_proxy_init(void *m)
+{
+    static const char path[] = "/rtas";
+    ofdn_t p;
+    ofdn_t n;
+    int i;
+
+    if (!rtas_proxy)
+        return -1;
+
+    printk("Create a new /rtas with tokens Xen is willing to proxy\n");
+
+    p = ofd_node_find(m, "/");
+
+    n = ofd_node_add(m, p, path, sizeof(path));
+    ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
+
+    /* and the tokens for proxy */
+    for (i = 0; i < ARRAY_SIZE(tokens); i++) {
+        if (tokens[i]->proxy && tokens[i]->token != -1)
+            ofd_prop_add(m, n, tokens[i]->name, &i, sizeof (i));
+    }
+    return n;
+}
+
+int do_rtas_proxy(ulong arg)
+{
+    struct rtas_args *r;
+    unsigned i;
+    int token;
+    ulong sz;
+
+    if (!IS_PRIV(current->domain))
+        return -EPERM;
+    if (!rtas_proxy)
+        return -ENOSYS;
+
+    /* has to be at least 5 words */
+    sz = (3 + 1 + 1) * sizeof (int);
+    r = rtas_remote_addr(arg, sz);
+    if (r == NULL) {
+        /* this is about all we can do at this point */
+        return -1;
+    }
+    /* make sure we can deal with everything */
+    sz = (3 + r->ra_nargs + r->ra_nrets) * sizeof (int);
+    if (rtas_remote_addr(arg, sz) == NULL) {
+        r->ra_args[r->ra_nargs] = RTAS_HW;
+        return -1;
+    }
+
+    i = r->ra_token;
+    token = tokens[i]->token;
+
+    if (i < ARRAY_SIZE(tokens) &&
+        tokens[i]->proxy != NULL &&
+        token != -1)
+        return tokens[i]->proxy(token, r);
+
+    return -1;
 }
 
 int
 rtas_halt(void)
 {
     struct rtas_args r;
-
-    if (rtas_halt_token == -1)
-        return -1;
-
-    r.ra_token = rtas_halt_token;
+    int token = tokens[RTAS_HALT]->token;
+
+    if (token == -1)
+        return -1;
+
+    r.ra_token = token;
     r.ra_nargs = 2;
     r.ra_nrets = 1;
     r.ra_args[0] = 0;
@@ -89,10 +186,12 @@ rtas_reboot(void)
 {
     struct rtas_args r;
 
-    if (rtas_reboot_token == -1)
-        return -ENOSYS;
-
-    r.ra_token = rtas_reboot_token;
+    int token = tokens[RTAS_REBOOT]->token;
+
+    if (token == -1)
+        return -1;
+
+    r.ra_token = token;
     r.ra_nargs = 2;
     r.ra_nrets = 1;
     r.ra_args[0] = 0;
diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/rtas.h
--- a/xen/arch/powerpc/rtas.h   Sun Jun 03 10:39:31 2007 -0400
+++ b/xen/arch/powerpc/rtas.h   Tue Jun 05 16:09:58 2007 -0400
@@ -26,9 +26,40 @@ extern unsigned long rtas_base;
 extern unsigned long rtas_base;
 extern unsigned long rtas_end;
 
+struct rtas_args {
+    int ra_token;
+    int ra_nargs;
+    int ra_nrets;
+    int ra_args[10];
+} __attribute__ ((aligned(8)));
+
+struct rtas_token {
+    char *name;
+    int (*proxy)(int token, struct rtas_args *r);
+    int token;
+};
+
+extern struct rtas_token rt_power_off;
+extern struct rtas_token rt_system_reboot;
+extern struct rtas_token rt_nvram_fetch;
+extern struct rtas_token rt_nvram_store;
+extern struct rtas_token rt_manage_flash;
+extern struct rtas_token rt_validate_flash;
+extern struct rtas_token rt_update_reboot_flash;
+
+/* RTAS errors */
+#define RTAS_HW -1
+#define RTAS_BUSY -2
+#define RTAS_PARAMETER -3
+
+
 extern int prom_call(void *arg, unsigned base,
                      unsigned long func, unsigned long msr);
 extern int rtas_init(void *);
 extern int rtas_halt(void);
 extern int rtas_reboot(void);
+extern int rtas_proxy_init(void *m);
+extern int do_rtas_proxy(ulong arg);
+extern void *rtas_remote_addr(ulong addr, ulong length);
+extern int rtas_call(void *r);
 #endif
diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/rtas_flash.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/rtas_flash.c     Tue Jun 05 16:09:58 2007 -0400
@@ -0,0 +1,182 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2007
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include "rtas.h"
+
+static int rtas_manage_flash(int token, struct rtas_args *ra)
+{
+    struct rtas_args r;
+    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
+    int ret;
+
+    if (ra->ra_nargs != 1 || ra->ra_nrets != 1) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+    memcpy(&r, ra, sz);
+    r.ra_token = token;
+
+    ret = rtas_call(&r);
+    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
+    return ret;
+}
+struct rtas_token rt_manage_flash = {
+    .name = "ibm,manage-flash-image",
+    .proxy = rtas_manage_flash,
+    .token = -1
+};
+
+static int rtas_validate_flash(int token, struct rtas_args *ra)
+{
+    ulong length = ra->ra_args[1];
+    char *buffer;
+    char *local;
+    struct rtas_args r;
+    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
+    int ret;
+
+    if (ra->ra_nargs != 2 || ra->ra_nrets != 2) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+
+    /* the original pointer can be in memory that is too high so we
+     * need to do it locally */
+    buffer = rtas_remote_addr(ra->ra_args[0], length);
+    if (buffer == NULL) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+        
+    local = xmalloc_bytes(length);
+    if (local == NULL) {
+        printk("%s: could not allocate local buffer size: 0x%lx\n",
+               __func__, length);
+        ra->ra_args[ra->ra_nargs] = RTAS_HW;
+        return -1;
+    }
+    /* RTAS is 32bits so we need to make sure that that local
+     * buffer is in that range */
+    BUG_ON(((ulong)local + length) & ~0xffffffffUL);
+
+    /* copy the remote buffer to the local one */
+    memcpy(local, buffer, length);
+
+    memcpy(&r, ra, sz);
+    r.ra_token = token;
+    r.ra_args[0] = (unsigned)(ulong)local;
+    ret = rtas_call(&r);
+    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
+    ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1];
+    xfree(local);
+    return ret;
+}
+
+struct rtas_token rt_validate_flash = {
+    .name = "ibm,validate-flash-image",
+    .proxy = rtas_validate_flash,
+    .token = -1
+};
+
+/* flash data structs */
+struct flash_block {
+    u64 addr;
+    u64 length;
+};
+struct flash_block_list {
+    struct {
+        u64 ver:8;
+        u64 bytes:56;
+    } header;
+    u64 *next;
+    struct flash_block blocks[0];
+};
+
+static int safe_to_flash;
+static int rtas_update_reboot_flash(int token, struct rtas_args *ra)
+{
+    struct rtas_args r;
+    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
+    int ret;
+    void *local;
+    struct flash_block_list *l;
+    ulong blocks;
+    
+    if (ra->ra_nargs != 1 || ra->ra_nrets != 1) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+
+    if (!safe_to_flash) {
+        printk("%s: this has not been fully tested yet\n", __func__);
+        ra->ra_args[ra->ra_nargs] = RTAS_HW;
+        return -1;
+    }
+
+    /* we only need to relocate the first block address to 4G, for now
+     * lets just bug on that */
+    local = rtas_remote_addr(ra->ra_args[0], 16);
+    BUG_ON((ulong)local & ~0xffffffffUL);
+
+    /* now we run through the block list and translate base addresses */
+    l = (struct flash_block_list *)local;
+
+    /* header and next count as one block */
+    blocks = (l->header.bytes / sizeof (struct flash_block)) - 1;
+    if (blocks == 0) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+
+    /* go thru the block lists */
+    do {
+        int i = 0;
+
+        /* go thru the block in the list */
+        for (i = 0; i < blocks; i++) {
+            void *addr;
+
+            addr = rtas_remote_addr(l->blocks[i].addr, l->blocks[i].length);
+            BUG_ON(addr == NULL);
+            l->blocks[i].addr = (u64)addr;
+        }
+        l = (struct flash_block_list *)l->next;
+    } while (l != NULL);
+
+    memcpy(&r, ra, sz);
+    r.ra_token = token;
+
+    /* this arguement is a pointer to a block list */
+    r.ra_args[0] = (unsigned)(ulong)local;
+
+    ret = rtas_call(&r);
+    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
+    return ret;
+}
+
+struct rtas_token rt_update_reboot_flash = {
+    .name = "ibm,update-flash-64-and-reboot",
+    .proxy = rtas_update_reboot_flash,
+    .token = -1
+};
diff -r 06a32f040d64 -r 6750b1320159 xen/arch/powerpc/rtas_nvram.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/rtas_nvram.c     Tue Jun 05 16:09:58 2007 -0400
@@ -0,0 +1,129 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2007
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include "rtas.h"
+
+static int rtas_nvram_store(int token, struct rtas_args *ra)
+{
+    ulong length = ra->ra_args[2];
+    char *buffer;
+    char *local;
+    struct rtas_args r;
+    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
+    int ret;
+
+    if (ra->ra_nargs != 3 || ra->ra_nrets != 2) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+
+    /* the original pointer can be in memory that is too high so we
+     * need to do it locally */
+    buffer = rtas_remote_addr(ra->ra_args[1], length);
+    if (buffer == NULL) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+        
+    local = xmalloc_bytes(length);
+    if (local == NULL) {
+        printk("%s: could not allocate local buffer size: 0x%lx\n",
+               __func__, length);
+        ra->ra_args[ra->ra_nargs] = RTAS_HW;
+        return -1;
+    }
+    /* RTAS is 32bits so we need to make sure that that local
+     * buffer is in that range */
+    BUG_ON(((ulong)local + length) & ~0xffffffffUL);
+
+    /* copy the remote buffer to the local one */
+    memcpy(local, buffer, length);
+
+    memcpy(&r, ra, sz);
+    r.ra_token = token;
+    r.ra_args[1] = (unsigned)(ulong)local;
+
+    ret = rtas_call(&r);
+    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
+    ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1];
+    xfree(local);
+    return ret;
+}
+
+struct rtas_token rt_nvram_store = {
+    .name = "nvram-store",
+    .proxy = rtas_nvram_store,
+    .token = -1
+};
+
+static int rtas_nvram_fetch(int token, struct rtas_args *ra)
+{
+    ulong length = ra->ra_args[2];
+    char *buffer;
+    char *local;
+    struct rtas_args r;
+    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
+    int ret;
+
+    if (ra->ra_nargs != 3 || ra->ra_nrets != 2) {
+        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
+        return -1;
+    }
+    /* the original pointer can be in ememory that is too high so
+     * we need to do it locally */
+    buffer = rtas_remote_addr(ra->ra_args[1], length);
+
+    local = xmalloc_bytes(length);
+    if (local == NULL) {
+        printk("%s: could not allocate local buffer size: 0x%lx\n",
+               __func__, length);
+        ra->ra_args[ra->ra_nargs] = RTAS_HW;
+        return -1;
+    }
+    /* RTAS is 32bits so we need to make sure that that local
+     * buffer is in that range */
+    BUG_ON(((ulong)local + length) & ~0xffffffffUL);
+
+    memcpy(&r, ra, sz);
+    r.ra_token = token;
+    r.ra_args[1] = (unsigned)(ulong)local;
+
+    ret = rtas_call(&r);
+    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
+    ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1];
+    if (r.ra_args[r.ra_nargs] >= 0) {
+        /* copy from local to remote */
+        sz = r.ra_args[r.ra_nargs + 1];
+        memcpy(buffer, local, sz);
+    }
+    xfree(local);
+    return ret;
+}
+
+struct rtas_token rt_nvram_fetch = {
+    .name = "nvram-fetch",
+    .proxy = rtas_nvram_fetch,
+    .token = -1
+};
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.