direct-io.hg

changeset 15491:6750b1320159

[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@watson.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Tue Jun 05 16:09:58 2007 -0400 (2007-06-05)
parents 06a32f040d64
children 8a8e6dfa6dea
files xen/arch/powerpc/Makefile xen/arch/powerpc/ofd_fixup.c xen/arch/powerpc/oftree.h xen/arch/powerpc/rtas.c xen/arch/powerpc/rtas.h xen/arch/powerpc/rtas_flash.c xen/arch/powerpc/rtas_nvram.c
line diff
     1.1 --- a/xen/arch/powerpc/Makefile	Sun Jun 03 10:39:31 2007 -0400
     1.2 +++ b/xen/arch/powerpc/Makefile	Tue Jun 05 16:09:58 2007 -0400
     1.3 @@ -35,6 +35,8 @@ obj-y += ofd_fixup_memory.o
     1.4  obj-y += physdev.o
     1.5  obj-y += platform.o
     1.6  obj-y += rtas.o
     1.7 +obj-y += rtas_nvram.o
     1.8 +obj-y += rtas_flash.o
     1.9  obj-y += setup.o
    1.10  obj-y += shadow.o
    1.11  obj-y += smp.o
     2.1 --- a/xen/arch/powerpc/ofd_fixup.c	Sun Jun 03 10:39:31 2007 -0400
     2.2 +++ b/xen/arch/powerpc/ofd_fixup.c	Tue Jun 05 16:09:58 2007 -0400
     2.3 @@ -27,8 +27,6 @@
     2.4  #include "oftree.h"
     2.5  #include "rtas.h"
     2.6  
     2.7 -#undef RTAS
     2.8 -
     2.9  ofdn_t ofd_boot_cpu;
    2.10  
    2.11  #ifdef PAPR_VTERM
    2.12 @@ -307,26 +305,6 @@ static ofdn_t ofd_chosen_props(void *m, 
    2.13      return n;
    2.14  }
    2.15  
    2.16 -#ifdef RTAS
    2.17 -static ofdn_t ofd_rtas_props(void *m)
    2.18 -{
    2.19 -    static const char path[] = "/rtas";
    2.20 -    static const char hypertas[] = "dummy";
    2.21 -    ofdn_t p;
    2.22 -    ofdn_t n;
    2.23 -
    2.24 -    /* just enough to make linux think its on LPAR */
    2.25 -
    2.26 -    p = ofd_node_find(m, "/");
    2.27 -
    2.28 -    n = ofd_node_add(m, p, path, sizeof(path));
    2.29 -    ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
    2.30 -    ofd_prop_add(m, n, "ibm,hypertas-functions", hypertas, sizeof (hypertas));
    2.31 -
    2.32 -    return n;
    2.33 -}
    2.34 -#endif
    2.35 -
    2.36  static ofdn_t ofd_xen_props(void *m, struct domain *d, ulong shared_info)
    2.37  {
    2.38      ofdn_t n;
    2.39 @@ -382,8 +360,8 @@ static ofdn_t ofd_xen_props(void *m, str
    2.40      return n;
    2.41  }
    2.42  
    2.43 -int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
    2.44 -                   ulong shared_info)
    2.45 +ulong ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
    2.46 +                     ulong shared_info)
    2.47  {
    2.48      void *m;
    2.49      const ofdn_t n = OFD_ROOT;
    2.50 @@ -423,11 +401,8 @@ int ofd_dom0_fixup(struct domain *d, ulo
    2.51      printk("Remove original /rtas\n");
    2.52      ofd_prune_path(m, "/rtas");
    2.53  
    2.54 -#ifdef RTAS
    2.55 -    printk("Create a new RTAS with just enough stuff to convince "
    2.56 -           "Linux that its on LPAR\n");
    2.57 -    ofd_rtas_props(m);
    2.58 -#endif
    2.59 +    rtas_proxy_init(m);
    2.60 +
    2.61  #ifdef FIX_COMPAT 
    2.62      const char compat[] = "Hypervisor,Maple";
    2.63      r = ofd_prop_add(m, n, "compatible", compat, sizeof (compat));
    2.64 @@ -446,5 +421,5 @@ int ofd_dom0_fixup(struct domain *d, ulo
    2.65  #ifdef DEBUG
    2.66      ofd_walk(m, __func__, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
    2.67  #endif
    2.68 -    return 1;
    2.69 +    return ofd_size(m);
    2.70  }
     3.1 --- a/xen/arch/powerpc/oftree.h	Sun Jun 03 10:39:31 2007 -0400
     3.2 +++ b/xen/arch/powerpc/oftree.h	Tue Jun 05 16:09:58 2007 -0400
     3.3 @@ -28,8 +28,8 @@ extern ulong oftree_len;
     3.4  extern ulong oftree_end;
     3.5  extern ofdn_t ofd_boot_cpu;
     3.6  
     3.7 -extern int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
     3.8 -                          ulong shared_info);
     3.9 +extern ulong ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
    3.10 +                            ulong shared_info);
    3.11  extern void ofd_memory_props(void *m, struct domain *d);
    3.12  
    3.13  extern int firmware_image_start[0];
     4.1 --- a/xen/arch/powerpc/rtas.c	Sun Jun 03 10:39:31 2007 -0400
     4.2 +++ b/xen/arch/powerpc/rtas.c	Tue Jun 05 16:09:58 2007 -0400
     4.3 @@ -13,7 +13,7 @@
     4.4   * along with this program; if not, write to the Free Software
     4.5   * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     4.6   *
     4.7 - * Copyright (C) IBM Corp. 2006
     4.8 + * Copyright (C) IBM Corp. 2006, 2007
     4.9   *
    4.10   * Authors: Jimi Xenidis <jimix@watson.ibm.com>
    4.11   */
    4.12 @@ -22,24 +22,16 @@
    4.13  #include <xen/init.h>
    4.14  #include <xen/lib.h>
    4.15  #include <xen/errno.h>
    4.16 +#include <xen/sched.h>
    4.17  #include "of-devtree.h"
    4.18  #include "rtas.h"
    4.19  
    4.20 -static int rtas_halt_token = -1;
    4.21 -static int rtas_reboot_token = -1;
    4.22  int rtas_entry;
    4.23  unsigned long rtas_msr;
    4.24  unsigned long rtas_base;
    4.25  unsigned long rtas_end;
    4.26  
    4.27 -struct rtas_args {
    4.28 -    int ra_token;
    4.29 -    int ra_nargs;
    4.30 -    int ra_nrets;
    4.31 -    int ra_args[10];
    4.32 -} __attribute__ ((aligned(8)));
    4.33 -
    4.34 -static int rtas_call(struct rtas_args *r)
    4.35 +int rtas_call(void *r)
    4.36  {
    4.37      if (rtas_entry == 0)
    4.38          return -ENOSYS;
    4.39 @@ -47,11 +39,51 @@ static int rtas_call(struct rtas_args *r
    4.40      return prom_call(r, rtas_base, rtas_entry, rtas_msr);
    4.41  }
    4.42  
    4.43 +/* rtas always uses physical address */
    4.44 +void *rtas_remote_addr(ulong addr, ulong length)
    4.45 +{
    4.46 +    struct vcpu *v = get_current();
    4.47 +    struct domain *d = v->domain;
    4.48 +    ulong mfn;
    4.49 +    ulong mfn_end;
    4.50 +
    4.51 +    mfn = gmfn_to_mfn(d, addr >> PAGE_SHIFT);
    4.52 +    if (mfn == INVALID_MFN)
    4.53 +        return NULL;
    4.54 +
    4.55 +    /* a little paranoid since almost everyone will pass us page
    4.56 +     * bounded thingies, but just in case */
    4.57 +    mfn_end = gmfn_to_mfn(d, (addr + length) >> PAGE_SHIFT);
    4.58 +    if (mfn_end == INVALID_MFN)
    4.59 +        return NULL;
    4.60 +
    4.61 +    return (void *)((mfn << PAGE_SHIFT) | (addr & (PAGE_SIZE - 1)));
    4.62 +}
    4.63 +
    4.64 +/* these do not proxy */
    4.65 +#define RTAS_HALT 0
    4.66 +#define RTAS_REBOOT 1
    4.67 +
    4.68 +struct rtas_token rt_power_off = { .name = "power-off", .token = -1, };
    4.69 +struct rtas_token rt_system_reboot = { .name = "system-reboot", .token = -1};
    4.70 +
    4.71 +static struct rtas_token *tokens[] = {
    4.72 +    /* these do not proxy */
    4.73 +    [RTAS_HALT] = &rt_power_off,
    4.74 +    [RTAS_REBOOT] = &rt_system_reboot,
    4.75 +    &rt_nvram_store,
    4.76 +    &rt_nvram_fetch,
    4.77 +    &rt_manage_flash,
    4.78 +    &rt_validate_flash,
    4.79 +    &rt_update_reboot_flash
    4.80 +};
    4.81 +
    4.82 +static int rtas_proxy;
    4.83 +
    4.84  int __init rtas_init(void *m)
    4.85  {
    4.86 -    static const char halt[] = "power-off";
    4.87 -    static const char reboot[] = "system-reboot";
    4.88      ofdn_t n;
    4.89 +    int i;
    4.90  
    4.91      if (rtas_entry == 0)
    4.92          return -ENOSYS;
    4.93 @@ -60,22 +92,87 @@ int __init rtas_init(void *m)
    4.94      if (n <= 0)
    4.95          return -ENOSYS;
    4.96  
    4.97 -    ofd_getprop(m, n, halt,
    4.98 -                &rtas_halt_token, sizeof (rtas_halt_token));
    4.99 -    ofd_getprop(m, n, reboot,
   4.100 -                &rtas_reboot_token, sizeof (rtas_reboot_token));
   4.101 +    for (i = 0; i < ARRAY_SIZE(tokens); i++) {
   4.102 +        ofd_getprop(m, n, tokens[i]->name,
   4.103 +                    &tokens[i]->token, sizeof (tokens[i]->token));
   4.104 +        if (!rtas_proxy && tokens[i]->proxy && tokens[i]->token != -1)
   4.105 +            rtas_proxy = 1;
   4.106 +    }
   4.107      return 1;
   4.108  }
   4.109  
   4.110 +int rtas_proxy_init(void *m)
   4.111 +{
   4.112 +    static const char path[] = "/rtas";
   4.113 +    ofdn_t p;
   4.114 +    ofdn_t n;
   4.115 +    int i;
   4.116 +
   4.117 +    if (!rtas_proxy)
   4.118 +        return -1;
   4.119 +
   4.120 +    printk("Create a new /rtas with tokens Xen is willing to proxy\n");
   4.121 +
   4.122 +    p = ofd_node_find(m, "/");
   4.123 +
   4.124 +    n = ofd_node_add(m, p, path, sizeof(path));
   4.125 +    ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
   4.126 +
   4.127 +    /* and the tokens for proxy */
   4.128 +    for (i = 0; i < ARRAY_SIZE(tokens); i++) {
   4.129 +        if (tokens[i]->proxy && tokens[i]->token != -1)
   4.130 +            ofd_prop_add(m, n, tokens[i]->name, &i, sizeof (i));
   4.131 +    }
   4.132 +    return n;
   4.133 +}
   4.134 +
   4.135 +int do_rtas_proxy(ulong arg)
   4.136 +{
   4.137 +    struct rtas_args *r;
   4.138 +    unsigned i;
   4.139 +    int token;
   4.140 +    ulong sz;
   4.141 +
   4.142 +    if (!IS_PRIV(current->domain))
   4.143 +        return -EPERM;
   4.144 +    if (!rtas_proxy)
   4.145 +        return -ENOSYS;
   4.146 +
   4.147 +    /* has to be at least 5 words */
   4.148 +    sz = (3 + 1 + 1) * sizeof (int);
   4.149 +    r = rtas_remote_addr(arg, sz);
   4.150 +    if (r == NULL) {
   4.151 +        /* this is about all we can do at this point */
   4.152 +        return -1;
   4.153 +    }
   4.154 +    /* make sure we can deal with everything */
   4.155 +    sz = (3 + r->ra_nargs + r->ra_nrets) * sizeof (int);
   4.156 +    if (rtas_remote_addr(arg, sz) == NULL) {
   4.157 +        r->ra_args[r->ra_nargs] = RTAS_HW;
   4.158 +        return -1;
   4.159 +    }
   4.160 +
   4.161 +    i = r->ra_token;
   4.162 +    token = tokens[i]->token;
   4.163 +
   4.164 +    if (i < ARRAY_SIZE(tokens) &&
   4.165 +        tokens[i]->proxy != NULL &&
   4.166 +        token != -1)
   4.167 +        return tokens[i]->proxy(token, r);
   4.168 +
   4.169 +    return -1;
   4.170 +}
   4.171 +
   4.172  int
   4.173  rtas_halt(void)
   4.174  {
   4.175      struct rtas_args r;
   4.176 +    int token = tokens[RTAS_HALT]->token;
   4.177  
   4.178 -    if (rtas_halt_token == -1)
   4.179 +    if (token == -1)
   4.180          return -1;
   4.181  
   4.182 -    r.ra_token = rtas_halt_token;
   4.183 +    r.ra_token = token;
   4.184      r.ra_nargs = 2;
   4.185      r.ra_nrets = 1;
   4.186      r.ra_args[0] = 0;
   4.187 @@ -89,10 +186,12 @@ rtas_reboot(void)
   4.188  {
   4.189      struct rtas_args r;
   4.190  
   4.191 -    if (rtas_reboot_token == -1)
   4.192 -        return -ENOSYS;
   4.193 +    int token = tokens[RTAS_REBOOT]->token;
   4.194  
   4.195 -    r.ra_token = rtas_reboot_token;
   4.196 +    if (token == -1)
   4.197 +        return -1;
   4.198 +
   4.199 +    r.ra_token = token;
   4.200      r.ra_nargs = 2;
   4.201      r.ra_nrets = 1;
   4.202      r.ra_args[0] = 0;
     5.1 --- a/xen/arch/powerpc/rtas.h	Sun Jun 03 10:39:31 2007 -0400
     5.2 +++ b/xen/arch/powerpc/rtas.h	Tue Jun 05 16:09:58 2007 -0400
     5.3 @@ -26,9 +26,40 @@ extern unsigned long rtas_msr;
     5.4  extern unsigned long rtas_base;
     5.5  extern unsigned long rtas_end;
     5.6  
     5.7 +struct rtas_args {
     5.8 +    int ra_token;
     5.9 +    int ra_nargs;
    5.10 +    int ra_nrets;
    5.11 +    int ra_args[10];
    5.12 +} __attribute__ ((aligned(8)));
    5.13 +
    5.14 +struct rtas_token {
    5.15 +    char *name;
    5.16 +    int (*proxy)(int token, struct rtas_args *r);
    5.17 +    int token;
    5.18 +};
    5.19 +
    5.20 +extern struct rtas_token rt_power_off;
    5.21 +extern struct rtas_token rt_system_reboot;
    5.22 +extern struct rtas_token rt_nvram_fetch;
    5.23 +extern struct rtas_token rt_nvram_store;
    5.24 +extern struct rtas_token rt_manage_flash;
    5.25 +extern struct rtas_token rt_validate_flash;
    5.26 +extern struct rtas_token rt_update_reboot_flash;
    5.27 +
    5.28 +/* RTAS errors */
    5.29 +#define RTAS_HW -1
    5.30 +#define RTAS_BUSY -2
    5.31 +#define RTAS_PARAMETER -3
    5.32 +
    5.33 +
    5.34  extern int prom_call(void *arg, unsigned base,
    5.35                       unsigned long func, unsigned long msr);
    5.36  extern int rtas_init(void *);
    5.37  extern int rtas_halt(void);
    5.38  extern int rtas_reboot(void);
    5.39 +extern int rtas_proxy_init(void *m);
    5.40 +extern int do_rtas_proxy(ulong arg);
    5.41 +extern void *rtas_remote_addr(ulong addr, ulong length);
    5.42 +extern int rtas_call(void *r);
    5.43  #endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/powerpc/rtas_flash.c	Tue Jun 05 16:09:58 2007 -0400
     6.3 @@ -0,0 +1,182 @@
     6.4 +/*
     6.5 + * This program is free software; you can redistribute it and/or modify
     6.6 + * it under the terms of the GNU General Public License as published by
     6.7 + * the Free Software Foundation; either version 2 of the License, or
     6.8 + * (at your option) any later version.
     6.9 + *
    6.10 + * This program is distributed in the hope that it will be useful,
    6.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.13 + * GNU General Public License for more details.
    6.14 + *
    6.15 + * You should have received a copy of the GNU General Public License
    6.16 + * along with this program; if not, write to the Free Software
    6.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    6.18 + *
    6.19 + * Copyright (C) IBM Corp. 2007
    6.20 + *
    6.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
    6.22 + */
    6.23 +
    6.24 +#include <xen/config.h>
    6.25 +#include <xen/init.h>
    6.26 +#include <xen/lib.h>
    6.27 +#include <xen/sched.h>
    6.28 +#include "rtas.h"
    6.29 +
    6.30 +static int rtas_manage_flash(int token, struct rtas_args *ra)
    6.31 +{
    6.32 +    struct rtas_args r;
    6.33 +    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
    6.34 +    int ret;
    6.35 +
    6.36 +    if (ra->ra_nargs != 1 || ra->ra_nrets != 1) {
    6.37 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
    6.38 +        return -1;
    6.39 +    }
    6.40 +    memcpy(&r, ra, sz);
    6.41 +    r.ra_token = token;
    6.42 +
    6.43 +    ret = rtas_call(&r);
    6.44 +    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
    6.45 +    return ret;
    6.46 +}
    6.47 +struct rtas_token rt_manage_flash = {
    6.48 +    .name = "ibm,manage-flash-image",
    6.49 +    .proxy = rtas_manage_flash,
    6.50 +    .token = -1
    6.51 +};
    6.52 +
    6.53 +static int rtas_validate_flash(int token, struct rtas_args *ra)
    6.54 +{
    6.55 +    ulong length = ra->ra_args[1];
    6.56 +    char *buffer;
    6.57 +    char *local;
    6.58 +    struct rtas_args r;
    6.59 +    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
    6.60 +    int ret;
    6.61 +
    6.62 +    if (ra->ra_nargs != 2 || ra->ra_nrets != 2) {
    6.63 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
    6.64 +        return -1;
    6.65 +    }
    6.66 +
    6.67 +    /* the original pointer can be in memory that is too high so we
    6.68 +     * need to do it locally */
    6.69 +    buffer = rtas_remote_addr(ra->ra_args[0], length);
    6.70 +    if (buffer == NULL) {
    6.71 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
    6.72 +        return -1;
    6.73 +    }
    6.74 +        
    6.75 +    local = xmalloc_bytes(length);
    6.76 +    if (local == NULL) {
    6.77 +        printk("%s: could not allocate local buffer size: 0x%lx\n",
    6.78 +               __func__, length);
    6.79 +        ra->ra_args[ra->ra_nargs] = RTAS_HW;
    6.80 +        return -1;
    6.81 +    }
    6.82 +    /* RTAS is 32bits so we need to make sure that that local
    6.83 +     * buffer is in that range */
    6.84 +    BUG_ON(((ulong)local + length) & ~0xffffffffUL);
    6.85 +
    6.86 +    /* copy the remote buffer to the local one */
    6.87 +    memcpy(local, buffer, length);
    6.88 +
    6.89 +    memcpy(&r, ra, sz);
    6.90 +    r.ra_token = token;
    6.91 +    r.ra_args[0] = (unsigned)(ulong)local;
    6.92 +    ret = rtas_call(&r);
    6.93 +    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
    6.94 +    ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1];
    6.95 +    xfree(local);
    6.96 +    return ret;
    6.97 +}
    6.98 +
    6.99 +struct rtas_token rt_validate_flash = {
   6.100 +    .name = "ibm,validate-flash-image",
   6.101 +    .proxy = rtas_validate_flash,
   6.102 +    .token = -1
   6.103 +};
   6.104 +
   6.105 +/* flash data structs */
   6.106 +struct flash_block {
   6.107 +    u64 addr;
   6.108 +    u64 length;
   6.109 +};
   6.110 +struct flash_block_list {
   6.111 +    struct {
   6.112 +        u64 ver:8;
   6.113 +        u64 bytes:56;
   6.114 +    } header;
   6.115 +    u64 *next;
   6.116 +    struct flash_block blocks[0];
   6.117 +};
   6.118 +
   6.119 +static int safe_to_flash;
   6.120 +static int rtas_update_reboot_flash(int token, struct rtas_args *ra)
   6.121 +{
   6.122 +    struct rtas_args r;
   6.123 +    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
   6.124 +    int ret;
   6.125 +    void *local;
   6.126 +    struct flash_block_list *l;
   6.127 +    ulong blocks;
   6.128 +    
   6.129 +    if (ra->ra_nargs != 1 || ra->ra_nrets != 1) {
   6.130 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
   6.131 +        return -1;
   6.132 +    }
   6.133 +
   6.134 +    if (!safe_to_flash) {
   6.135 +        printk("%s: this has not been fully tested yet\n", __func__);
   6.136 +        ra->ra_args[ra->ra_nargs] = RTAS_HW;
   6.137 +        return -1;
   6.138 +    }
   6.139 +
   6.140 +    /* we only need to relocate the first block address to 4G, for now
   6.141 +     * lets just bug on that */
   6.142 +    local = rtas_remote_addr(ra->ra_args[0], 16);
   6.143 +    BUG_ON((ulong)local & ~0xffffffffUL);
   6.144 +
   6.145 +    /* now we run through the block list and translate base addresses */
   6.146 +    l = (struct flash_block_list *)local;
   6.147 +
   6.148 +    /* header and next count as one block */
   6.149 +    blocks = (l->header.bytes / sizeof (struct flash_block)) - 1;
   6.150 +    if (blocks == 0) {
   6.151 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
   6.152 +        return -1;
   6.153 +    }
   6.154 +
   6.155 +    /* go thru the block lists */
   6.156 +    do {
   6.157 +        int i = 0;
   6.158 +
   6.159 +        /* go thru the block in the list */
   6.160 +        for (i = 0; i < blocks; i++) {
   6.161 +            void *addr;
   6.162 +
   6.163 +            addr = rtas_remote_addr(l->blocks[i].addr, l->blocks[i].length);
   6.164 +            BUG_ON(addr == NULL);
   6.165 +            l->blocks[i].addr = (u64)addr;
   6.166 +        }
   6.167 +        l = (struct flash_block_list *)l->next;
   6.168 +    } while (l != NULL);
   6.169 +
   6.170 +    memcpy(&r, ra, sz);
   6.171 +    r.ra_token = token;
   6.172 +
   6.173 +    /* this arguement is a pointer to a block list */
   6.174 +    r.ra_args[0] = (unsigned)(ulong)local;
   6.175 +
   6.176 +    ret = rtas_call(&r);
   6.177 +    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
   6.178 +    return ret;
   6.179 +}
   6.180 +
   6.181 +struct rtas_token rt_update_reboot_flash = {
   6.182 +    .name = "ibm,update-flash-64-and-reboot",
   6.183 +    .proxy = rtas_update_reboot_flash,
   6.184 +    .token = -1
   6.185 +};
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/arch/powerpc/rtas_nvram.c	Tue Jun 05 16:09:58 2007 -0400
     7.3 @@ -0,0 +1,129 @@
     7.4 +/*
     7.5 + * This program is free software; you can redistribute it and/or modify
     7.6 + * it under the terms of the GNU General Public License as published by
     7.7 + * the Free Software Foundation; either version 2 of the License, or
     7.8 + * (at your option) any later version.
     7.9 + *
    7.10 + * This program is distributed in the hope that it will be useful,
    7.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.13 + * GNU General Public License for more details.
    7.14 + *
    7.15 + * You should have received a copy of the GNU General Public License
    7.16 + * along with this program; if not, write to the Free Software
    7.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    7.18 + *
    7.19 + * Copyright (C) IBM Corp. 2007
    7.20 + *
    7.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
    7.22 + */
    7.23 +
    7.24 +#include <xen/config.h>
    7.25 +#include <xen/init.h>
    7.26 +#include <xen/lib.h>
    7.27 +#include <xen/sched.h>
    7.28 +#include "rtas.h"
    7.29 +
    7.30 +static int rtas_nvram_store(int token, struct rtas_args *ra)
    7.31 +{
    7.32 +    ulong length = ra->ra_args[2];
    7.33 +    char *buffer;
    7.34 +    char *local;
    7.35 +    struct rtas_args r;
    7.36 +    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
    7.37 +    int ret;
    7.38 +
    7.39 +    if (ra->ra_nargs != 3 || ra->ra_nrets != 2) {
    7.40 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
    7.41 +        return -1;
    7.42 +    }
    7.43 +
    7.44 +    /* the original pointer can be in memory that is too high so we
    7.45 +     * need to do it locally */
    7.46 +    buffer = rtas_remote_addr(ra->ra_args[1], length);
    7.47 +    if (buffer == NULL) {
    7.48 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
    7.49 +        return -1;
    7.50 +    }
    7.51 +        
    7.52 +    local = xmalloc_bytes(length);
    7.53 +    if (local == NULL) {
    7.54 +        printk("%s: could not allocate local buffer size: 0x%lx\n",
    7.55 +               __func__, length);
    7.56 +        ra->ra_args[ra->ra_nargs] = RTAS_HW;
    7.57 +        return -1;
    7.58 +    }
    7.59 +    /* RTAS is 32bits so we need to make sure that that local
    7.60 +     * buffer is in that range */
    7.61 +    BUG_ON(((ulong)local + length) & ~0xffffffffUL);
    7.62 +
    7.63 +    /* copy the remote buffer to the local one */
    7.64 +    memcpy(local, buffer, length);
    7.65 +
    7.66 +    memcpy(&r, ra, sz);
    7.67 +    r.ra_token = token;
    7.68 +    r.ra_args[1] = (unsigned)(ulong)local;
    7.69 +
    7.70 +    ret = rtas_call(&r);
    7.71 +    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
    7.72 +    ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1];
    7.73 +    xfree(local);
    7.74 +    return ret;
    7.75 +}
    7.76 +
    7.77 +struct rtas_token rt_nvram_store = {
    7.78 +    .name = "nvram-store",
    7.79 +    .proxy = rtas_nvram_store,
    7.80 +    .token = -1
    7.81 +};
    7.82 +
    7.83 +static int rtas_nvram_fetch(int token, struct rtas_args *ra)
    7.84 +{
    7.85 +    ulong length = ra->ra_args[2];
    7.86 +    char *buffer;
    7.87 +    char *local;
    7.88 +    struct rtas_args r;
    7.89 +    ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int);
    7.90 +    int ret;
    7.91 +
    7.92 +    if (ra->ra_nargs != 3 || ra->ra_nrets != 2) {
    7.93 +        ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER;
    7.94 +        return -1;
    7.95 +    }
    7.96 +    /* the original pointer can be in ememory that is too high so
    7.97 +     * we need to do it locally */
    7.98 +    buffer = rtas_remote_addr(ra->ra_args[1], length);
    7.99 +
   7.100 +    local = xmalloc_bytes(length);
   7.101 +    if (local == NULL) {
   7.102 +        printk("%s: could not allocate local buffer size: 0x%lx\n",
   7.103 +               __func__, length);
   7.104 +        ra->ra_args[ra->ra_nargs] = RTAS_HW;
   7.105 +        return -1;
   7.106 +    }
   7.107 +    /* RTAS is 32bits so we need to make sure that that local
   7.108 +     * buffer is in that range */
   7.109 +    BUG_ON(((ulong)local + length) & ~0xffffffffUL);
   7.110 +
   7.111 +    memcpy(&r, ra, sz);
   7.112 +    r.ra_token = token;
   7.113 +    r.ra_args[1] = (unsigned)(ulong)local;
   7.114 +
   7.115 +    ret = rtas_call(&r);
   7.116 +    ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs];
   7.117 +    ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1];
   7.118 +    if (r.ra_args[r.ra_nargs] >= 0) {
   7.119 +        /* copy from local to remote */
   7.120 +        sz = r.ra_args[r.ra_nargs + 1];
   7.121 +        memcpy(buffer, local, sz);
   7.122 +    }
   7.123 +    xfree(local);
   7.124 +    return ret;
   7.125 +}
   7.126 +
   7.127 +struct rtas_token rt_nvram_fetch = {
   7.128 +    .name = "nvram-fetch",
   7.129 +    .proxy = rtas_nvram_fetch,
   7.130 +    .token = -1
   7.131 +};
   7.132 +