home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / sim / ppc / emul_chirp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-21  |  42.5 KB  |  1,584 lines

  1. /*  This file is part of the program psim.
  2.  
  3.     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19.     */
  20.  
  21.  
  22. #ifndef _EMUL_CHIRP_C_
  23. #define _EMUL_CHIRP_C_
  24.  
  25. /* Note: this module is called via a table.  There is no benefit in
  26.    making it inline */
  27.  
  28. #include "emul_generic.h"
  29. #include "emul_chirp.h"
  30.  
  31. #ifdef HAVE_STRING_H
  32. #include <string.h>
  33. #else
  34. #ifdef HAVE_STRINGS_H
  35. #include <strings.h>
  36. #endif
  37. #endif
  38.  
  39. #include <unistd.h>
  40.  
  41. #ifndef STATIC_INLINE_EMUL_CHIRP
  42. #define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
  43. #endif
  44.  
  45.  
  46. /* Descriptor of the open boot services being emulated */
  47.  
  48. typedef int (chirp_handler)
  49.      (os_emul_data *data,
  50.       cpu *processor,
  51.       unsigned_word cia);
  52. typedef struct _chirp_services {
  53.   const char *name;
  54.   chirp_handler *handler;
  55. } chirp_services;
  56.  
  57.  
  58. /* The OpenBoot emulation is, at any time either waiting for a client
  59.    request or waiting on a client callback */
  60. typedef enum {
  61.   serving,
  62.   emulating,
  63.   faulting,
  64. } chirp_emul_state;
  65.  
  66. struct _os_emul_data {
  67.   chirp_emul_state state;
  68.   unsigned_word return_address;
  69.   unsigned_word arguments;
  70.   unsigned_word n_args;
  71.   unsigned_word n_returns;
  72.   chirp_services *service;
  73.   device *root;
  74.   chirp_services *services;
  75.   /* configuration */
  76.   unsigned_word memory_size;
  77.   unsigned_word virt_base;
  78.   int little_endian;
  79.   int real_mode;
  80.   int floating_point_available;
  81.   int interrupt_prefix;
  82.   /* hash table */
  83.   unsigned_word nr_page_table_entry_groups;
  84.   unsigned_word htab_ra;
  85.   unsigned_word htab_va;
  86.   unsigned_word sizeof_htab;
  87.   /* virtual address of htab */
  88.   unsigned_word stack_ra;
  89.   unsigned_word stack_va;
  90.   unsigned_word sizeof_stack;
  91.   /* addresses of emulation instructions virtual/real */
  92.   unsigned_word code_va;
  93.   unsigned_word code_ra;
  94.   unsigned_word sizeof_code;
  95.   unsigned_word code_client_va;
  96.   unsigned_word code_client_ra;
  97.   unsigned_word code_callback_va;
  98.   unsigned_word code_callback_ra;
  99.   unsigned_word code_loop_va;
  100.   unsigned_word code_loop_ra;
  101. };
  102.  
  103.  
  104. /* Read/write the argument list making certain that all values are
  105.    converted to/from host byte order.
  106.  
  107.    In the below only n_args+n_returns is read/written */
  108.  
  109. static int
  110. chirp_read_t2h_args(void *args,
  111.             int sizeof_args,
  112.             int n_args,
  113.             int n_returns,
  114.             os_emul_data *data,
  115.             cpu *processor,
  116.             unsigned_word cia)
  117. {
  118.   unsigned32 *words;
  119.   int i;
  120.   /* check the number of arguments */
  121.   if ((n_args >= 0 && data->n_args != n_args)
  122.       || (n_returns >= 0 && data->n_returns != n_returns)) {
  123.     TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
  124.               data->service->name,
  125.               (long)data->n_args,
  126.               (long)data->n_returns));
  127.     return -1;
  128.   }
  129.   /* check that there is enough space */
  130.   if (sizeof(unsigned32) * (data->n_args + data->n_returns) > sizeof_args)
  131.     return -1;
  132.   /* bring in the data */
  133.   emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned32),
  134.            sizeof(unsigned32) * (data->n_args + data->n_returns),
  135.            processor, cia);
  136.   /* convert all words to host format */
  137.   words = args;
  138.   for (i = 0; i < (sizeof_args / sizeof(unsigned32)); i++)
  139.     words[i] = T2H_4(words[i]);
  140.   return 0;
  141. }
  142.  
  143. static void
  144. chirp_write_h2t_args(void *args,
  145.              int sizeof_args,
  146.              os_emul_data *data,
  147.              cpu *processor,
  148.              unsigned_word cia)
  149. {
  150.   int i;
  151.   unsigned32 *words;
  152.   /* convert to target everything */
  153.   words = args;
  154.   for (i = 0; i < (sizeof_args / sizeof(unsigned32)); i++)
  155.     words[i] = H2T_4(words[i]);
  156.   /* bring in the data */
  157.   emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned32),
  158.             sizeof(unsigned32) * (data->n_args + data->n_returns),
  159.             processor, cia);
  160. }
  161.  
  162.  
  163. /* OpenBoot emulation functions */
  164.  
  165. /* client interface */
  166.  
  167. static int
  168. chirp_emul_test(os_emul_data *data,
  169.         cpu *processor,
  170.         unsigned_word cia)
  171. {
  172.   struct test_args {
  173.     /*in*/
  174.     unsigned32 name; /*string*/
  175.     /*out*/
  176.     unsigned32 missing;
  177.   } args;
  178.   char name[32];
  179.   chirp_services *service = NULL;
  180.   /* read in the arguments */
  181.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  182.     return -1;
  183.   emul_read_string(name, args.name, sizeof(name),
  184.            processor, cia);
  185.   TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
  186.   /* see if we know about the service */
  187.   service = data->services;
  188.   while (service->name != NULL && strcmp(service->name, name) != 0) {
  189.     service++;
  190.   }
  191.   if (service->name == NULL)
  192.     args.missing = -1;
  193.   else
  194.     args.missing = 0;
  195.   /* write the arguments back out */
  196.   TRACE(trace_os_emul, ("test - out - missing=%ld\n",
  197.             (long)args.missing));
  198.   chirp_write_h2t_args(&args,
  199.                sizeof(args),
  200.                data,
  201.                processor, cia);
  202.   return 0;
  203. }
  204.  
  205.  
  206. /* Device tree */
  207.  
  208. static int
  209. chirp_emul_peer(os_emul_data *data,
  210.         cpu *processor,
  211.         unsigned_word cia)
  212. {
  213.   struct peer_args {
  214.     /*in*/
  215.     unsigned32 phandle;
  216.     /*out*/
  217.     unsigned32 sibling_phandle;
  218.   } args;
  219.   device *phandle;
  220.   device *sibling_phandle = NULL;
  221.   /* read in the arguments */
  222.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  223.     return -1;
  224.   phandle = external_to_device(data->root, args.phandle);
  225.   TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
  226.             (unsigned long)args.phandle,
  227.             (unsigned long)phandle,
  228.             (phandle == NULL ? "" : device_name(phandle))));
  229.   /* find the peer */
  230.   if (args.phandle == 0) {
  231.     sibling_phandle = data->root;
  232.     args.sibling_phandle = device_to_external(sibling_phandle);
  233.   }
  234.   else if (phandle == NULL) {
  235.     sibling_phandle = NULL;
  236.     args.sibling_phandle = -1;
  237.   }
  238.   else {
  239.     sibling_phandle = device_sibling(phandle);
  240.     args.sibling_phandle = device_to_external(sibling_phandle);
  241.   }
  242.   /* write the arguments back out */
  243.   TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
  244.             (unsigned long)args.sibling_phandle,
  245.             (unsigned long)sibling_phandle,
  246.             (sibling_phandle == NULL ? "" : device_name(sibling_phandle))));
  247.   chirp_write_h2t_args(&args,
  248.                sizeof(args),
  249.                data,
  250.                processor, cia);
  251.   return 0;
  252. }
  253.  
  254. static int
  255. chirp_emul_child(os_emul_data *data,
  256.          cpu *processor,
  257.          unsigned_word cia)
  258. {
  259.   struct child_args {
  260.     /*in*/
  261.     unsigned32 phandle;
  262.     /*out*/
  263.     unsigned32 child_phandle;
  264.   } args;
  265.   device *phandle;
  266.   device *child_phandle;
  267.   /* read the arguments in */
  268.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  269.     return -1;
  270.   phandle = external_to_device(data->root, args.phandle);
  271.   TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
  272.             (unsigned long)args.phandle,
  273.             (unsigned long)phandle,
  274.             (phandle == NULL ? "" : device_name(phandle))));
  275.   /* find a child */
  276.   if (args.phandle == 0
  277.       || phandle == NULL) {
  278.     child_phandle = NULL;
  279.     args.child_phandle = -1;
  280.   }
  281.   else {
  282.     child_phandle = device_child(phandle);
  283.     args.child_phandle = device_to_external(child_phandle);
  284.   }
  285.   /* write the result out */
  286.   TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
  287.             (unsigned long)args.child_phandle,
  288.             (unsigned long)child_phandle,
  289.             (child_phandle == NULL ? "" : device_name(child_phandle))));
  290.   chirp_write_h2t_args(&args,
  291.                sizeof(args),
  292.                data,
  293.                processor, cia);
  294.   return 0;
  295. }
  296.  
  297. static int
  298. chirp_emul_parent(os_emul_data *data,
  299.           cpu *processor,
  300.           unsigned_word cia)
  301. {
  302.   struct parent_args {
  303.     /*in*/
  304.     unsigned32 phandle;
  305.     /*out*/
  306.     unsigned32 parent_phandle;
  307.   } args;
  308.   device *phandle;
  309.   device *parent_phandle;
  310.   /* read the args in */
  311.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  312.     return -1;
  313.   phandle = external_to_device(data->root, args.phandle);
  314.   TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
  315.             (unsigned long)args.phandle,
  316.             (unsigned long)phandle,
  317.             (phandle == NULL ? "" : device_name(phandle))));
  318.   /* find a parent */
  319.   if (args.phandle == 0
  320.       || phandle == NULL) {
  321.     parent_phandle = NULL;
  322.     args.parent_phandle = -1;
  323.   }
  324.   else {
  325.     parent_phandle = device_parent(phandle);
  326.     args.parent_phandle = device_to_external(parent_phandle);
  327.   }
  328.   /* return the result */
  329.   TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
  330.             (unsigned long)args.parent_phandle,
  331.             (unsigned long)parent_phandle,
  332.             (parent_phandle == NULL ? "" : device_name(parent_phandle))));
  333.   chirp_write_h2t_args(&args,
  334.                sizeof(args),
  335.                data,
  336.                processor, cia);
  337.   return 0;
  338. }
  339.  
  340. static int
  341. chirp_emul_instance_to_package(os_emul_data *data,
  342.                    cpu *processor,
  343.                    unsigned_word cia)
  344. {
  345.   struct instance_to_package_args {
  346.     /*in*/
  347.     unsigned32 ihandle;
  348.     /*out*/
  349.     unsigned32 phandle;
  350.   } args;
  351.   device_instance *ihandle;
  352.   device *phandle = NULL;
  353.   /* read the args in */
  354.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  355.     return -1;
  356.   ihandle = external_to_device_instance(data->root, args.ihandle);
  357.   TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
  358.             (unsigned long)args.ihandle,
  359.             (unsigned long)ihandle,
  360.             (ihandle == NULL ? "" : device_instance_name(ihandle))));
  361.   /* find the corresponding phandle */
  362.   if (args.ihandle == 0
  363.       || ihandle == NULL) {
  364.     phandle = NULL;
  365.     args.phandle = -1;
  366.   }
  367.   else {
  368.     phandle = device_instance_device(ihandle);
  369.     args.phandle = device_to_external(phandle);
  370.   }
  371.   /* return the result */
  372.   TRACE(trace_os_emul, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
  373.             (unsigned long)args.phandle,
  374.             (unsigned long)phandle,
  375.             (phandle == NULL ? "" : device_name(phandle))));
  376.   chirp_write_h2t_args(&args,
  377.                sizeof(args),
  378.                data,
  379.                processor, cia);
  380.   return 0;
  381. }
  382.  
  383. static int
  384. chirp_emul_getproplen(os_emul_data *data,
  385.               cpu *processor,
  386.               unsigned_word cia)
  387. {
  388.   struct getproplen_args {
  389.     /*in*/
  390.     unsigned32 phandle;
  391.     unsigned32 name;
  392.     /*out*/
  393.     unsigned32 proplen;
  394.   } args;
  395.   char name[32];
  396.   device *phandle;
  397.   /* read the args in */
  398.   if (chirp_read_t2h_args(&args, sizeof(args), 2, 1, data, processor, cia))
  399.     return -1;
  400.   phandle = external_to_device(data->root, args.phandle);
  401.   emul_read_string(name,
  402.            args.name,
  403.            sizeof(name),
  404.            processor, cia);
  405.   TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
  406.             (unsigned long)args.phandle,
  407.             (unsigned long)phandle,
  408.             (phandle == NULL ? "" : device_name(phandle)),
  409.             name));
  410.   /* find our prop and get its length */
  411.   if (args.phandle == 0
  412.       || phandle == NULL) {
  413.     args.proplen = -1;
  414.   }
  415.   else {
  416.     const device_property *prop = device_find_property(phandle, name);
  417.     if (prop == (device_property*)0) {
  418.       args.proplen = -1;
  419.     }
  420.     else {
  421.       args.proplen = prop->sizeof_array;
  422.     }
  423.   }
  424.   /* return the result */
  425.   TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
  426.             (unsigned long)args.proplen));
  427.   chirp_write_h2t_args(&args,
  428.                sizeof(args),
  429.                data,
  430.                processor, cia);
  431.   return 0;
  432. }
  433.  
  434. static int
  435. chirp_emul_getprop(os_emul_data *data,
  436.            cpu *processor,
  437.            unsigned_word cia)
  438. {
  439.   struct getprop_args {
  440.     /*in*/
  441.     unsigned32 phandle;
  442.     unsigned32 name;
  443.     unsigned32 buf;
  444.     unsigned32 buflen;
  445.     /*out*/
  446.     unsigned32 size;
  447.   } args;
  448.   char name[32];
  449.   device *phandle;
  450.   /* read in the args, the return is optional */
  451.   if (chirp_read_t2h_args(&args, sizeof(args), 4, -1, data, processor, cia))
  452.     return -1;
  453.   phandle = external_to_device(data->root, args.phandle);
  454.   emul_read_string(name,
  455.            args.name,
  456.            sizeof(name),
  457.            processor, cia);
  458.   TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
  459.             (unsigned long)args.phandle,
  460.             (unsigned long)phandle,
  461.             (phandle == NULL ? "" : device_name(phandle)),
  462.             name,
  463.             (unsigned long)args.buf,
  464.             (unsigned long)args.buflen));
  465.   /* get the property */
  466.   if (args.phandle == 0
  467.       || phandle == NULL) {
  468.     args.size = -1;
  469.   }
  470.   else {
  471.     const device_property *prop = device_find_property(phandle, name);
  472.     if (prop == NULL) {
  473.       args.size = -1;
  474.     }
  475.     else {
  476.       int size = args.buflen;
  477.       if (size > prop->sizeof_array)
  478.     size = prop->sizeof_array;
  479.       emul_write_buffer(prop->array, args.buf,
  480.             size,
  481.             processor, cia);
  482.       args.size = size;
  483.       switch (prop->type) {
  484.       case string_property:
  485.     TRACE(trace_os_emul, ("getprop - string `%s'\n",
  486.                   device_find_string_property(phandle, name)));
  487.     break;
  488.       case ihandle_property:
  489.     TRACE(trace_os_emul, ("getprop - ihandle 0x%lx\n",
  490.                   (unsigned long)device_find_ihandle_property(phandle, name)));
  491.     break;
  492.       default:
  493.     break;
  494.       }
  495.     }
  496.   }
  497.   /* write back the result */
  498.   if (data->n_returns == 0)
  499.     TRACE(trace_os_emul, ("getprop - out - size=%ld (not returned)\n",
  500.               (unsigned long)args.size));
  501.   else {
  502.     TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
  503.               (unsigned long)args.size));
  504.     chirp_write_h2t_args(&args,
  505.              sizeof(args),
  506.              data,
  507.              processor, cia);
  508.   }
  509.   return 0;
  510. }
  511.  
  512. static int
  513. chirp_emul_nextprop(os_emul_data *data,
  514.             cpu *processor,
  515.             unsigned_word cia)
  516. {
  517.   struct nextprop_args {
  518.     /*in*/
  519.     unsigned32 phandle;
  520.     unsigned32 previous;
  521.     unsigned32 buf;
  522.     /*out*/
  523.     unsigned32 flag;
  524.   } args;
  525.   char previous[32];
  526.   device *phandle;
  527.   /* read in the args */
  528.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  529.     return -1;
  530.   phandle = external_to_device(data->root, args.phandle);
  531.   emul_read_string(previous,
  532.            args.previous,
  533.            sizeof(previous),
  534.            processor, cia);
  535.   TRACE(trace_os_emul, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
  536.             (unsigned long)args.phandle,
  537.             (unsigned long)phandle,
  538.             (phandle == NULL ? "" : device_name(phandle)),
  539.             previous,
  540.             (unsigned long)args.buf));
  541.   /* find the next property */
  542.   if (args.phandle == 0
  543.       || phandle == NULL) {
  544.     args.flag = -1;
  545.   }
  546.   else {
  547.     const device_property *prev_prop = device_find_property(phandle, previous);
  548.     if (prev_prop == NULL) {
  549.       args.flag = -1; /* name invalid */
  550.     }
  551.     else {
  552.       const device_property *next_prop;
  553.       next_prop = device_next_property(prev_prop);
  554.       if (next_prop == NULL) {
  555.     args.flag = 0; /* last property */
  556.       }
  557.       else {
  558.     emul_write_buffer(next_prop->name, args.buf, strlen(next_prop->name),
  559.               processor, cia);
  560.     TRACE(trace_os_emul, ("nextprop - name=`%s'\n", next_prop->name));
  561.     args.flag = 1; /* worked ok */
  562.       }
  563.     }
  564.   }
  565.   /* write back the result */
  566.   TRACE(trace_os_emul, ("nextprop - out - flag=%ld\n",
  567.             (unsigned long)args.flag));
  568.   chirp_write_h2t_args(&args,
  569.                sizeof(args),
  570.                data,
  571.                processor, cia);
  572.   return 0;
  573. }
  574.  
  575. #if 0
  576. static int
  577. chirp_emul_setprop(os_emul_data *data,
  578.            cpu *processor,
  579.            unsigned_word cia)
  580. {
  581.   error("chirp: setprop not implemented\n");
  582.   return 0;
  583. }
  584. #endif
  585.  
  586. static int
  587. chirp_emul_canon(os_emul_data *data,
  588.          cpu *processor,
  589.          unsigned_word cia)
  590. {
  591.   struct canon_args {
  592.     /*in*/
  593.     unsigned32 device_specifier;
  594.     unsigned32 buf;
  595.     unsigned32 buflen;
  596.     /*out*/
  597.     unsigned32 length;
  598.   } args;
  599.   char device_specifier[1024];
  600.   device *phandle;
  601.   const char *path;
  602.   int length;
  603.   /* read in the args */
  604.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  605.     return -1;
  606.   emul_read_string(device_specifier,
  607.            args.device_specifier,
  608.            sizeof(device_specifier),
  609.            processor, cia);
  610.   TRACE(trace_os_emul, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
  611.             device_specifier,
  612.             (unsigned long)args.buf,
  613.             (unsigned long)args.buflen));
  614.   /* canon the name */
  615.   phandle = device_tree_find_device(data->root, device_specifier);
  616.   if (phandle == NULL) {
  617.     length = -1;
  618.     path = "";
  619.     args.length = -1;
  620.   }
  621.   else {
  622.     path = device_path(phandle);
  623.     length = strlen(path);
  624.     if (length >= args.buflen)
  625.       length = args.buflen - 1;
  626.     emul_write_buffer(path, args.buf, length,
  627.               processor, cia);
  628.     args.length = length;
  629.   }
  630.   /* write back the result */
  631.   TRACE(trace_os_emul, ("canon - out - length=%ld buf=`%s'\n",
  632.             (unsigned long)args.length,
  633.             path));
  634.   chirp_write_h2t_args(&args,
  635.                sizeof(args),
  636.                data,
  637.                processor, cia);
  638.   return 0;
  639. }
  640.  
  641. static int
  642. chirp_emul_finddevice(os_emul_data *data,
  643.               cpu *processor,
  644.               unsigned_word cia)
  645. {
  646.   struct finddevice_args {
  647.     /*in*/
  648.     unsigned32 device_specifier;
  649.     /*out*/
  650.     unsigned32 phandle;
  651.   } args;
  652.   char device_specifier[1024];
  653.   device *phandle;
  654.   /* get the args */
  655.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  656.     return -1;
  657.   emul_read_string(device_specifier,
  658.            args.device_specifier,
  659.            sizeof(device_specifier),
  660.            processor, cia);
  661.   TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
  662.             device_specifier));
  663.   /* find the device */
  664.   phandle = device_tree_find_device(data->root,
  665.              device_specifier);
  666.   if (phandle == NULL)
  667.     args.phandle = -1;
  668.   else
  669.     args.phandle = device_to_external(phandle);
  670.   /* return its phandle */
  671.   TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
  672.             (unsigned long)args.phandle,
  673.             (unsigned long)phandle,
  674.             (phandle == NULL ? "" : device_name(phandle))));
  675.   chirp_write_h2t_args(&args,
  676.                sizeof(args),
  677.                data,
  678.                processor, cia);
  679.   return 0;
  680. }
  681.  
  682. static int
  683. chirp_emul_instance_to_path(os_emul_data *data,
  684.                 cpu *processor,
  685.                 unsigned_word cia)
  686. {
  687.   struct instance_to_path_args {
  688.     /*in*/
  689.     unsigned32 ihandle;
  690.     unsigned32 buf;
  691.     unsigned32 buflen;
  692.     /*out*/
  693.     unsigned32 length;
  694.   } args;
  695.   device_instance *ihandle;
  696.   const char *path;
  697.   int length;
  698.   /* get the args */
  699.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  700.     return -1;
  701.   ihandle = external_to_device_instance(data->root, args.ihandle);
  702.   TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
  703.             (unsigned long)args.ihandle,
  704.             (unsigned long)ihandle,
  705.             (ihandle == NULL ? "" : device_instance_name(ihandle)),
  706.             (unsigned long)args.buf,
  707.             (unsigned long)args.buflen));
  708.   /* get the devices name */
  709.   if (ihandle == NULL)
  710.     return -1;
  711.   path = device_instance_path(ihandle);
  712.   length = strlen(path);
  713.   if (length >= args.buflen)
  714.     length = args.buflen - 1;
  715.   emul_write_buffer(path, args.buf, length,
  716.             processor, cia);
  717.   /* return its phandle */
  718.   TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n",
  719.             (unsigned long)args.length,
  720.             path));
  721.   chirp_write_h2t_args(&args,
  722.                sizeof(args),
  723.                data,
  724.                processor, cia);
  725.   return 0;
  726. }
  727.  
  728. static int
  729. chirp_emul_package_to_path(os_emul_data *data,
  730.                 cpu *processor,
  731.                 unsigned_word cia)
  732. {
  733.   struct package_to_path_args {
  734.     /*in*/
  735.     unsigned32 phandle;
  736.     unsigned32 buf;
  737.     unsigned32 buflen;
  738.     /*out*/
  739.     unsigned32 length;
  740.   } args;
  741.   device *phandle;
  742.   const char *path;
  743.   int length;
  744.   /* get the args */
  745.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  746.     return -1;
  747.   phandle = external_to_device(data->root, args.phandle);
  748.   TRACE(trace_os_emul, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
  749.             (unsigned long)args.phandle,
  750.             (unsigned long)phandle,
  751.             (phandle == NULL ? "" : device_name(phandle)),
  752.             (unsigned long)args.buf,
  753.             (unsigned long)args.buflen));
  754.   /* get the devices name */
  755.   if (phandle == NULL)
  756.     return -1;
  757.   path = device_path(phandle);
  758.   length = strlen(path);
  759.   if (length >= args.buflen)
  760.     length = args.buflen - 1;
  761.   emul_write_buffer(path, args.buf, length,
  762.             processor, cia);
  763.   /* return its phandle */
  764.   TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n",
  765.             (unsigned long)args.length,
  766.             path));
  767.   chirp_write_h2t_args(&args,
  768.                sizeof(args),
  769.                data,
  770.                processor, cia);
  771.   return 0;
  772. }
  773.  
  774. static int
  775. chirp_emul_call_method(os_emul_data *data,
  776.                cpu *processor,
  777.                unsigned_word cia)
  778. {
  779.   struct call_method_args {
  780.     /*in*/
  781.     unsigned32 method;
  782.     unsigned32 ihandle;
  783.     /*in/out*/
  784.     unsigned32 stack[13]; /*6in + 6out + catch */
  785.   } args;
  786.   char method[32];
  787.   device_instance *ihandle;
  788.   /* read the args */
  789.   if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia))
  790.     return -1;
  791.   emul_read_string(method,
  792.            args.method,
  793.            sizeof(method),
  794.            processor, cia);
  795.   ihandle = external_to_device_instance(data->root, args.ihandle);
  796.   TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
  797.             (unsigned long)data->n_args,
  798.             (unsigned long)data->n_returns,
  799.             method,
  800.             (unsigned long)args.ihandle,
  801.             (unsigned long)ihandle,
  802.             (ihandle == NULL ? "" : device_instance_name(ihandle))));
  803.   printf_filtered("warning chirp: call-method %s not implemented\n", method);
  804.   args.stack[data->n_args-2+1] = 0;
  805.   chirp_write_h2t_args(&args,
  806.                sizeof(args),
  807.                data,
  808.                processor, cia);
  809.   return 0;
  810. }
  811.  
  812.  
  813. /* Device I/O */
  814.  
  815. static int
  816. chirp_emul_open(os_emul_data *data,
  817.         cpu *processor,
  818.         unsigned_word cia)
  819. {
  820.   struct open_args {
  821.     /*in*/
  822.     unsigned32 device_specifier;
  823.     /*out*/
  824.     unsigned32 ihandle;
  825.   } args;
  826.   char device_specifier[1024];
  827.   device_instance *ihandle;
  828.   /* read the args */
  829.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  830.     return -1;
  831.   emul_read_string(device_specifier,
  832.            args.device_specifier,
  833.            sizeof(device_specifier),
  834.            processor, cia);
  835.   TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
  836.             device_specifier));
  837.   /* open the device */
  838.   ihandle = device_instance_create(data->root, device_specifier, 0);
  839.   if (ihandle == NULL)
  840.     args.ihandle = -1;
  841.   else
  842.     args.ihandle = device_instance_to_external(ihandle);
  843.   /* return the ihandle result */
  844.   TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
  845.             (unsigned long)args.ihandle,
  846.             (unsigned long)ihandle,
  847.             (ihandle == NULL ? "" : device_instance_name(ihandle))));
  848.   chirp_write_h2t_args(&args,
  849.                sizeof(args),
  850.                data,
  851.                processor, cia);
  852.   return 0;
  853. }
  854.  
  855. static int
  856. chirp_emul_close(os_emul_data *data,
  857.          cpu *processor,
  858.          unsigned_word cia)
  859. {
  860.   struct close_args {
  861.     /*in*/
  862.     unsigned32 ihandle;
  863.     /*out*/
  864.   } args;
  865.   device_instance *ihandle;
  866.   /* read the args */
  867.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 0, data, processor, cia))
  868.     return -1;
  869.   ihandle = external_to_device_instance(data->root, args.ihandle);
  870.   TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
  871.             (unsigned long)args.ihandle,
  872.             (unsigned long)ihandle,
  873.             (ihandle == NULL ? "" : device_instance_name(ihandle))));
  874.   /* close the device */
  875.   if (ihandle != NULL)
  876.     device_instance_delete(ihandle);
  877.   /* return the ihandle result */
  878.   TRACE(trace_os_emul, ("close - out\n"));
  879.   chirp_write_h2t_args(&args,
  880.                sizeof(args),
  881.                data,
  882.                processor, cia);
  883.   return 0;
  884. }
  885.  
  886. static int
  887. chirp_emul_read(os_emul_data *data,
  888.         cpu *processor,
  889.         unsigned_word cia)
  890. {
  891.   struct read_args {
  892.     /*in*/
  893.     unsigned32 ihandle;
  894.     unsigned32 addr;
  895.     unsigned32 len;
  896.     /*out*/
  897.     unsigned32 actual;
  898.   } args;
  899.   char buf[1024];
  900.   int actual;
  901.   device_instance *ihandle;
  902.   /* read the args */
  903.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  904.     return -1;
  905.   ihandle = external_to_device_instance(data->root, args.ihandle);
  906.   TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
  907.             (unsigned long)args.ihandle,
  908.             (unsigned long)ihandle,
  909.             (ihandle == NULL ? "" : device_instance_name(ihandle)),
  910.             (unsigned long)args.addr,
  911.             (unsigned long)args.len));
  912.   if (ihandle == NULL)
  913.     return -1;
  914.   /* do the read */
  915.   actual = args.len;
  916.   if (actual >= sizeof(buf))
  917.     actual = sizeof(buf) - 1;
  918.   actual = device_instance_read(ihandle, buf, actual);
  919.   if (actual >= 0) {
  920.     emul_write_buffer(buf,
  921.               args.addr,
  922.               actual,
  923.               processor, cia);
  924.     args.actual = actual;
  925.     buf[actual] = '\0';
  926.   }
  927.   else {
  928.     args.actual = 0;
  929.   }
  930.   /* return the result */
  931.   TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
  932.             (long)args.actual,
  933.             (actual >= 0 ? buf : "")));
  934.   chirp_write_h2t_args(&args,
  935.                sizeof(args),
  936.                data,
  937.                processor, cia);
  938.   return 0;
  939. }
  940.  
  941. static int
  942. chirp_emul_write(os_emul_data *data,
  943.         cpu *processor,
  944.         unsigned_word cia)
  945. {
  946.   struct write_args {
  947.     /*in*/
  948.     unsigned32 ihandle;
  949.     unsigned32 addr;
  950.     unsigned32 len;
  951.     /*out*/
  952.     unsigned32 actual;
  953.   } args;
  954.   char buf[1024];
  955.   device_instance *ihandle;
  956.   int actual;
  957.   /* get the args */
  958.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  959.     return -1;
  960.   actual = args.len;
  961.   if (actual >= sizeof(buf))
  962.     actual = sizeof(buf) - 1;
  963.   emul_read_buffer(buf,
  964.            args.addr,
  965.            actual,
  966.            processor, cia);
  967.   buf[actual] = '\0';
  968.   ihandle = external_to_device_instance(data->root, args.ihandle);
  969.   TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
  970.             (unsigned long)args.ihandle,
  971.             (unsigned long)ihandle,
  972.             (ihandle == NULL ? "" : device_instance_name(ihandle)),
  973.             buf, (long)actual));
  974.   if (ihandle == NULL)
  975.     return -1;
  976.   /* write it out */
  977.   actual = device_instance_write(ihandle, buf, actual);
  978.   if (actual < 0)
  979.     args.actual = 0;
  980.   else
  981.     args.actual = actual;
  982.   /* return the result */
  983.   TRACE(trace_os_emul, ("write - out - actual=%ld\n",
  984.             (long)args.actual));
  985.   chirp_write_h2t_args(&args,
  986.                sizeof(args),
  987.                data,
  988.                processor, cia);
  989.   return 0;
  990. }
  991.  
  992. static int
  993. chirp_emul_seek(os_emul_data *data,
  994.         cpu *processor,
  995.         unsigned_word cia)
  996. {
  997.   struct seek_args {
  998.     /*in*/
  999.     unsigned32 ihandle;
  1000.     unsigned32 pos_hi;
  1001.     unsigned32 pos_lo;
  1002.     /*out*/
  1003.     unsigned32 status;
  1004.   } args;
  1005.   int status;
  1006.   device_instance *ihandle;
  1007.   /* get the args */
  1008.   if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
  1009.     return -1;
  1010.   ihandle = external_to_device_instance(data->root, args.ihandle);
  1011.   TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
  1012.             (unsigned long)args.ihandle,
  1013.             (unsigned long)ihandle,
  1014.             (ihandle == NULL ? "" : device_instance_name(ihandle)),
  1015.             args.pos_hi, args.pos_lo));
  1016.   if (ihandle == NULL)
  1017.     return -1;
  1018.   /* seek it out */
  1019.   if (ihandle == NULL)
  1020.     return -1;
  1021.   status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo);
  1022.   args.status = status;
  1023.   /* return the result */
  1024.   TRACE(trace_os_emul, ("seek - out - status=%ld\n",
  1025.             (long)args.status));
  1026.   chirp_write_h2t_args(&args,
  1027.                sizeof(args),
  1028.                data,
  1029.                processor, cia);
  1030.   return 0;
  1031. }
  1032.  
  1033.  
  1034. /* memory */
  1035.  
  1036. static int
  1037. chirp_emul_claim(os_emul_data *data,
  1038.          cpu *processor,
  1039.          unsigned_word cia)
  1040. {
  1041.   error("chirp: claim not implemented\n");
  1042.   return 0;
  1043. }
  1044.  
  1045. static int
  1046. chirp_emul_release(os_emul_data *data,
  1047.            cpu *processor,
  1048.            unsigned_word cia)
  1049. {
  1050.   error("chirp: release not implemented\n");
  1051.   return 0;
  1052. }
  1053.  
  1054.  
  1055. /* Control transfer */
  1056.  
  1057. static int
  1058. chirp_emul_boot(os_emul_data *data,
  1059.         cpu *processor,
  1060.         unsigned_word cia)
  1061. {
  1062.   error("chirp: boot not implemented\n");
  1063.   return 0;
  1064. }
  1065.  
  1066. static int
  1067. chirp_emul_enter(os_emul_data *data,
  1068.          cpu *processor,
  1069.          unsigned_word cia)
  1070. {
  1071.   error("chirp: enter not implemented\n");
  1072.   return 0;
  1073. }
  1074.  
  1075. static int
  1076. chirp_emul_exit(os_emul_data *data,
  1077.         cpu *processor,
  1078.         unsigned_word cia)
  1079. {
  1080.   cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
  1081.   return 0;
  1082. }
  1083.  
  1084. static int
  1085. chirp_emul_chain(os_emul_data *data,
  1086.          cpu *processor,
  1087.          unsigned_word cia)
  1088. {
  1089.   error("chirp: chain not implemented\n");
  1090.   return 0;
  1091. }
  1092.  
  1093.  
  1094. /* user interface */
  1095.  
  1096. static int
  1097. chirp_emul_interpret(os_emul_data *data,
  1098.              cpu *processor,
  1099.              unsigned_word cia)
  1100. {
  1101.   error("chirp: interpret not implemented\n");
  1102.   return 0;
  1103. }
  1104.  
  1105. static int
  1106. chirp_emul_set_callback(os_emul_data *data,
  1107.             cpu *processor,
  1108.             unsigned_word cia)
  1109. {
  1110.   error("chirp: set_callback not implemented\n");
  1111.   return 0;
  1112. }
  1113.  
  1114. static int
  1115. chirp_emul_set_symbol_lookup(os_emul_data *data,
  1116.                  cpu *processor,
  1117.                  unsigned_word cia)
  1118. {
  1119.   error("chirp: set_symbol_lookup not implemented\n");
  1120.   return 0;
  1121. }
  1122.  
  1123.  
  1124. /* Time */
  1125.  
  1126. static int
  1127. chirp_emul_milliseconds(os_emul_data *data,
  1128.             cpu *processor,
  1129.             unsigned_word cia)
  1130. {
  1131.   struct test_args {
  1132.     /*in*/
  1133.     /*out*/
  1134.     unsigned32 ms;
  1135.   } args;
  1136.   unsigned64 time;
  1137.   /* read in the arguments */
  1138.   if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
  1139.     return -1;
  1140.   /* make up a number */
  1141.   time = event_queue_time(cpu_event_queue(processor)) / 1000000;
  1142.   args.ms = time;
  1143.   /* write the arguments back out */
  1144.   TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
  1145.             (unsigned long)args.ms));
  1146.   chirp_write_h2t_args(&args,
  1147.                sizeof(args),
  1148.                data,
  1149.                processor, cia);
  1150.   return 0;
  1151. }
  1152.  
  1153.  
  1154.  
  1155.  
  1156. static chirp_services services[] = {
  1157.  
  1158.   /* client interface */
  1159.   { "test", chirp_emul_test },
  1160.  
  1161.   /* device tree */
  1162.   { "peer", chirp_emul_peer },
  1163.   { "child", chirp_emul_child },
  1164.   { "parent", chirp_emul_parent },
  1165.   { "instance-to-package", chirp_emul_instance_to_package },
  1166.   { "getproplen", chirp_emul_getproplen },
  1167.   { "getprop", chirp_emul_getprop },
  1168.   { "nextprop", chirp_emul_nextprop },
  1169.   /* { "setprop", chirp_emul_setprop }, */
  1170.   { "canon", chirp_emul_canon },
  1171.   { "finddevice", chirp_emul_finddevice },
  1172.   { "instance-to-path", chirp_emul_instance_to_path },
  1173.   { "package-to-path", chirp_emul_package_to_path },
  1174.   { "call-method", chirp_emul_call_method },
  1175.  
  1176.   /* device I/O */
  1177.   { "open", chirp_emul_open },
  1178.   { "close", chirp_emul_close },
  1179.   { "read", chirp_emul_read },
  1180.   { "write", chirp_emul_write },
  1181.   { "seek", chirp_emul_seek },
  1182.   { "write", chirp_emul_write },
  1183.  
  1184.   /* memory */
  1185.   { "claim", chirp_emul_claim },
  1186.   { "release", chirp_emul_release },
  1187.  
  1188.   /* control transfer */
  1189.   { "boot", chirp_emul_boot },
  1190.   { "enter", chirp_emul_enter },
  1191.   { "exit", chirp_emul_exit },
  1192.   { "chain", chirp_emul_chain },
  1193.  
  1194.   /* user interface */
  1195.   { "interpret", chirp_emul_interpret },
  1196.   { "set_callback", chirp_emul_set_callback },
  1197.   { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
  1198.  
  1199.   /* time */
  1200.   { "milliseconds", chirp_emul_milliseconds },
  1201.  
  1202.   { 0, /* sentinal */ },
  1203. };
  1204.  
  1205.  
  1206. /* main handlers */
  1207.  
  1208. /* Any starting address greater than this is assumed to be an Chirp
  1209.    rather than VEA */
  1210.  
  1211. #ifndef CHIRP_START_ADDRESS
  1212. #define CHIRP_START_ADDRESS 0x80000000
  1213. #endif
  1214.  
  1215. typedef struct _chirp_note_desc {
  1216.   signed32 real_mode;
  1217.   signed32 real_base;
  1218.   signed32 real_size;
  1219.   signed32 virt_base;
  1220.   signed32 virt_size;
  1221. } chirp_note_desc;
  1222.  
  1223. typedef struct _chirp_note {
  1224.   chirp_note_desc desc;
  1225.   int found;
  1226. } chirp_note;
  1227.  
  1228. typedef struct _chirp_note_head {
  1229.   unsigned32 namesz;
  1230.   unsigned32 descsz;
  1231.   unsigned32 type;
  1232. } chirp_note_head;
  1233.  
  1234. static void
  1235. map_over_chirp_note(bfd *image,
  1236.             asection *sect,
  1237.             PTR obj)
  1238. {
  1239.   chirp_note *note = (chirp_note*)obj;
  1240.   if (strcmp(sect->name, ".note") == 0) {
  1241.     chirp_note_head head;
  1242.     char name[16];
  1243.     /* check the head */
  1244.     if (!bfd_get_section_contents(image, sect,
  1245.                   &head, 0, sizeof(head)))
  1246.       return;
  1247.     head.namesz = bfd_get_32(image, (void*)&head.namesz);
  1248.     head.descsz = bfd_get_32(image, (void*)&head.descsz);
  1249.     head.type = bfd_get_32(image, (void*)&head.type);
  1250.     if (head.type != 0x1275)
  1251.       return;
  1252.     note->found = 1;
  1253.     /* check the name field */
  1254.     if (head.namesz > sizeof(name)) {
  1255.       printf_filtered("open-boot warning: note name too long (%ld)\n",
  1256.               (long)head.namesz);
  1257.       return;
  1258.     }
  1259.     if (!bfd_get_section_contents(image, sect,
  1260.                   name, sizeof(head), head.namesz)) {
  1261.       printf_filtered("open-boot warning: note name unreadable\n");
  1262.       return;
  1263.     }
  1264.     if (strcmp(name, "PowerPC") != 0) {
  1265.       printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
  1266.               name);
  1267.       return;
  1268.     }
  1269.     /* get the contents */
  1270.     if (head.descsz != sizeof(note->desc)) {
  1271.       printf_filtered("open-boot warning: note descriptor of wrong size\n");
  1272.       return;
  1273.     }
  1274.     if (!bfd_get_section_contents(image, sect,
  1275.                   ¬e->desc, /* page align start */
  1276.                   ((sizeof(head) + head.namesz) + 3) & ~3,
  1277.                   head.descsz)) {
  1278.       printf_filtered("open-boot warning: note descriptor unreadable\n");
  1279.       return;
  1280.     }
  1281.     note->desc.real_mode = bfd_get_32(image, (void*)¬e->desc.real_mode);
  1282.     note->desc.real_base = bfd_get_32(image, (void*)¬e->desc.real_base);
  1283.     note->desc.real_size = bfd_get_32(image, (void*)¬e->desc.real_size);
  1284.     note->desc.virt_base = bfd_get_32(image, (void*)¬e->desc.virt_base);
  1285.     note->desc.virt_size = bfd_get_32(image, (void*)¬e->desc.virt_size);
  1286.     note->found = 2;
  1287.   }
  1288. }
  1289.  
  1290.  
  1291. static os_emul_data *
  1292. emul_chirp_create(device *root,
  1293.           bfd *image,
  1294.           const char *name)
  1295. {
  1296.   os_emul_data *chirp;
  1297.   device *node;
  1298.   chirp_note note;
  1299.  
  1300.   /* Sanity check that this really is the chosen emulation */
  1301.   if (name == NULL && image == NULL)
  1302.     return NULL;
  1303.   if (name != NULL
  1304.       && strcmp(name, "ob") != 0
  1305.       && strcmp(name, "ieee1274") != 0
  1306.       && strcmp(name, "chrp") != 0
  1307.       && strcmp(name, "chirp") != 0
  1308.       && strcmp(name, "openboot") != 0)
  1309.     return NULL;
  1310.  
  1311.   /* look for an elf note section */
  1312.   memset(¬e, 0, sizeof(note));
  1313.   if (image != NULL)
  1314.     bfd_map_over_sections(image, map_over_chirp_note, ¬e);
  1315.   if (name == NULL && image != NULL && !note.found)
  1316.     return NULL;
  1317.  
  1318.   /* the root node */
  1319.   device_add_string_property(root,
  1320.                  "name",
  1321.                  "gpl,clayton");
  1322.  
  1323.   /* default options */
  1324.   emul_add_tree_options(root, image, "chirp", "oea",
  1325.             0 /*oea-interrupt-prefix*/);
  1326.     
  1327.   /* hardware */
  1328.   emul_add_tree_hardware(root);
  1329.     
  1330.   /* basic information */
  1331.   chirp = ZALLOC(os_emul_data);
  1332.   chirp->memory_size
  1333.     = device_find_integer_property(root, "/openprom/options/oea-memory-size");
  1334.   chirp->little_endian
  1335.     = device_find_boolean_property(root, "/options/little-endian?");
  1336.   chirp->floating_point_available
  1337.     = device_find_boolean_property(root, "/openprom/options/floating-point?");
  1338.   chirp->interrupt_prefix =
  1339.     device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
  1340.  
  1341.   chirp->root = root;
  1342.   chirp->services = services;
  1343.  
  1344.   /* the hash table */
  1345.   chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000
  1346.                        ? 1024 /* min allowed */
  1347.                        : (chirp->memory_size / 4096 / 2));
  1348.   chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;
  1349.   chirp->htab_ra = chirp->memory_size - chirp->sizeof_htab;
  1350.     
  1351.   /* a page for firmware calls */
  1352.   chirp->sizeof_code = 4096;
  1353.   chirp->code_ra = chirp->htab_ra - chirp->sizeof_code;
  1354.     
  1355.   /* the stack */
  1356.   chirp->sizeof_stack = 32 * 1024;
  1357.   chirp->stack_ra = chirp->code_ra - chirp->sizeof_stack;
  1358.     
  1359.   /* the firmware's home */
  1360.   chirp->real_mode = 0;
  1361.   /*  const unsigned_word real_base = stack_ra; */
  1362.   /*  const unsigned real_size = memory_size - real_base; */
  1363.   chirp->virt_base = CHIRP_START_ADDRESS;
  1364.   /*  const unsigned virt_size = real_size;*/
  1365.     
  1366.   /* the virtual addresses */
  1367.   chirp->htab_va = chirp->code_va + chirp->sizeof_code;
  1368.   chirp->stack_va = chirp->virt_base;
  1369.   chirp->code_va = chirp->stack_va + chirp->sizeof_stack;
  1370.  
  1371.   chirp->code_client_va = chirp->code_va;
  1372.   chirp->code_client_ra = chirp->code_ra;
  1373.  
  1374.   chirp->code_callback_va = chirp->code_client_va + 16;
  1375.   chirp->code_callback_ra = chirp->code_client_ra + 16;
  1376.  
  1377.   chirp->code_loop_va = chirp->code_callback_va + 16;
  1378.   chirp->code_loop_ra = chirp->code_callback_ra + 16;
  1379.     
  1380.   /* initialization */
  1381.   device_tree_add_parsed(root, "/openprom/init");
  1382.   device_tree_add_parsed(root, "/openprom/init/register");
  1383.   device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx",
  1384.              (unsigned long)bfd_get_start_address(image));
  1385.   device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
  1386.              (unsigned long)chirp->code_loop_va);
  1387.   device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
  1388.              (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
  1389.   device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
  1390.              (msr_machine_check_enable
  1391.               | (chirp->real_mode
  1392.                  ? 0 
  1393.                  : (msr_instruction_relocate
  1394.                 | msr_data_relocate))
  1395.               | (chirp->little_endian
  1396.                  ? (msr_little_endian_mode
  1397.                 | msr_interrupt_little_endian_mode)
  1398.                  : 0)
  1399.               | (chirp->floating_point_available
  1400.                  ? msr_floating_point_available
  1401.                  : 0)
  1402.               | (chirp->interrupt_prefix
  1403.                  ? msr_interrupt_prefix
  1404.                  : 0)
  1405.               ));
  1406.   device_tree_add_parsed(root, "/openprom/init/register/sdr1 0x%lx",
  1407.              (unsigned long)(chirp->htab_ra
  1408.                      | MASK32(16, 22)
  1409.                      | ((chirp->sizeof_htab - 1) >> 16)));
  1410.   /* FIXME */
  1411.   device_tree_add_parsed(root, "/openprom/init/register/sr8 0x%x",
  1412.              0x00fffff8);
  1413.   device_tree_add_parsed(root, "/openprom/init/register/sr9 0x%x",
  1414.              0x00fffff9);
  1415.   
  1416.   
  1417.   /* init the code callback along with a loop for the unused cpu's */
  1418.   device_tree_add_parsed(root, "/openprom/init/register/r5 0x%lx",
  1419.              (unsigned long)chirp->code_client_va);
  1420.   
  1421.   /* client interface - emul-call followed by return instruction */
  1422.   
  1423.   node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
  1424.              (unsigned long)chirp->code_client_ra);
  1425.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1426.              (unsigned long)chirp->code_client_ra);
  1427.   device_tree_add_parsed(node, "./data 0x%lx",
  1428.              (unsigned long)emul_call_instruction);
  1429.   
  1430.   node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
  1431.                 (unsigned long)(chirp->code_client_ra + 4));
  1432.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1433.              (unsigned long)(chirp->code_client_ra + 4));
  1434.   device_tree_add_parsed(node, "./data 0x%lx",
  1435.              (unsigned long)emul_blr_instruction);
  1436.   
  1437.   /* return address for client callbacks - an emul-call instruction */
  1438.   
  1439.   node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
  1440.                 (unsigned long)chirp->code_callback_ra);
  1441.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1442.              (unsigned long)chirp->code_callback_ra);
  1443.   device_tree_add_parsed(node, "./data 0x%lx",
  1444.              (unsigned long)emul_call_instruction);
  1445.   
  1446.   /* loop to keep other processors busy */
  1447.   
  1448.   node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
  1449.                 (unsigned long)chirp->code_loop_ra);
  1450.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1451.              (unsigned long)chirp->code_loop_ra);
  1452.   device_tree_add_parsed(node, "./data 0x%lx",
  1453.              (unsigned long)emul_loop_instruction);
  1454.   
  1455.   /* hash table and vm */
  1456.   node = device_tree_add_parsed(root, "/openprom/init/htab@0x%lx",
  1457.                 (unsigned long)chirp->htab_ra);
  1458.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1459.              (unsigned long)chirp->htab_ra);
  1460.   device_tree_add_parsed(node, "./nr-bytes 0x%lx",
  1461.              (unsigned long)chirp->sizeof_htab);
  1462.   
  1463.   node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
  1464.                 (unsigned long)chirp->stack_ra);
  1465.   device_tree_add_parsed(node, "./virtual-address 0x%lx",
  1466.              (unsigned long)chirp->stack_va);
  1467.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1468.              (unsigned long)chirp->stack_ra);
  1469.   device_tree_add_parsed(node, "./nr-bytes 0x%lx",
  1470.              (unsigned long)chirp->sizeof_stack);
  1471.   device_tree_add_parsed(node, "./wimg %d", 0x7);
  1472.   device_tree_add_parsed(node, "./pp %d", 0x2);
  1473.   
  1474.   node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
  1475.                 (unsigned long)chirp->code_ra);
  1476.   device_tree_add_parsed(node, "./virtual-address 0x%lx",
  1477.              (unsigned long)chirp->code_va);
  1478.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1479.              (unsigned long)chirp->code_ra);
  1480.   device_tree_add_parsed(node, "./nr-bytes 0x%lx",
  1481.              (unsigned long)chirp->sizeof_code);
  1482.   device_tree_add_parsed(node, "./wimg %d", 0x7);
  1483.   device_tree_add_parsed(node, "./pp %d", 0x2);
  1484.   
  1485.   node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
  1486.                 (unsigned long)chirp->htab_ra);
  1487.   device_tree_add_parsed(node, "./virtual-address 0x%lx",
  1488.              (unsigned long)chirp->htab_va);
  1489.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1490.              (unsigned long)chirp->htab_ra);
  1491.   device_tree_add_parsed(node, "./nr-bytes 0x%lx",
  1492.              (unsigned long)chirp->sizeof_stack);
  1493.   device_tree_add_parsed(node, "./wimg %d", 0x7);
  1494.   device_tree_add_parsed(node, "./pp %d", 0x2);
  1495.   
  1496.   node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
  1497.                 (unsigned long)0x4000 /*magic*/);
  1498.   device_tree_add_parsed(node, "./real-address 0x%lx",
  1499.              (unsigned long)0x4000);
  1500.   device_tree_add_parsed(node, "./file-name \"%s", bfd_get_filename(image));
  1501.   device_tree_add_parsed(node, "./wimg %d", 0x7);
  1502.   device_tree_add_parsed(node, "./pp %d", 0x2);
  1503.   
  1504.   return chirp;
  1505. }
  1506.  
  1507. static void
  1508. emul_chirp_init(os_emul_data *emul_data,
  1509.         int nr_cpus)
  1510. {
  1511.   emul_data->state = serving;
  1512. }
  1513.  
  1514. static int
  1515. emul_chirp_instruction_call(cpu *processor,
  1516.                 unsigned_word cia,
  1517.                 unsigned_word ra,
  1518.                 os_emul_data *emul_data)
  1519. {
  1520.   unsigned_word service_name_addr;
  1521.   unsigned_word result;
  1522.   char service_buf[32];
  1523.   char *service_name;
  1524.   chirp_services *service;
  1525.   
  1526.   switch (emul_data->state) {
  1527.     
  1528.   case serving:
  1529.     /* we are waiting on an OpenBoot request from the client program
  1530.        via the client interface */
  1531.     if (cia != emul_data->code_client_va)
  1532.       return 0;
  1533.     emul_data->return_address = LR;
  1534.     emul_data->arguments = cpu_registers(processor)->gpr[3];
  1535.     /* try to determine what to do */
  1536.     service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3],
  1537.                        processor, cia);
  1538.     service_name = emul_read_string(service_buf, service_name_addr,
  1539.                     sizeof(service_buf), processor, cia);
  1540.     emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned32),
  1541.                        processor, cia);
  1542.     emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned32),
  1543.                       processor, cia);
  1544.     TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
  1545.               service_name,
  1546.               (unsigned long)emul_data->return_address,
  1547.               (unsigned long)emul_data->arguments));
  1548.     /* look it up */
  1549.     service = services;
  1550.     while (service->name != NULL && strcmp(service->name, service_name) != 0)
  1551.       service++;
  1552.     if (service->name == NULL) {
  1553.       error("OpenBoot service `%s' not found\n", service_name);
  1554.       TRACE(trace_os_emul, ("%s not found\n", service_name));
  1555.       cpu_registers(processor)->gpr[3] = 0;
  1556.       cpu_restart(processor, emul_data->return_address);
  1557.     }
  1558.     emul_data->service = service;
  1559.     /* call upon it */
  1560.     result = service->handler(emul_data, processor, cia);
  1561.     break;
  1562.  
  1563.   default:
  1564.     error("emul_chirp_instruction_call() unknown internal state\n");
  1565.     result = -1;
  1566.     break;
  1567.  
  1568.   }
  1569.  
  1570.   /* return to caller - instruction following this is a function return */
  1571.   return 1;
  1572. }
  1573.  
  1574. const os_emul emul_chirp = {
  1575.   "chirp",
  1576.   emul_chirp_create,
  1577.   emul_chirp_init,
  1578.   NULL, /*system_call*/
  1579.   emul_chirp_instruction_call,
  1580.   0 /*data*/
  1581. };
  1582.  
  1583. #endif
  1584.