WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [POWERPC][XEN] Set up an RTAS node for do

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [POWERPC][XEN] Set up an RTAS node for dom0 and proxy methods
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 09 Jul 2007 04:22:17 -0700
Delivery-date: Mon, 09 Jul 2007 04:20:33 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [POWERPC][XEN] Set up an RTAS node for dom0 and proxy methods, Xen patchbot-unstable <=