1/*  This file is part of the program psim.
2
3    Copyright 1994, 1997, 2003, 2004 Andrew Cagney
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 _HW_INIT_C_
23#define _HW_INIT_C_
24
25#include "device_table.h"
26#include "bfd.h"
27#include "psim.h"
28
29
30/* DMA a file into memory */
31static int
32dma_file(device *me,
33	 const char *file_name,
34	 unsigned_word addr)
35{
36  int count;
37  int inc;
38  FILE *image;
39  char buf[1024];
40
41  /* get it open */
42  image = fopen(file_name, "r");
43  if (image == NULL)
44    return -1;
45
46  /* read it in slowly */
47  count = 0;
48  while (1) {
49    inc = fread(buf, 1, sizeof(buf), image);
50    if (inc <= 0)
51      break;
52    if (device_dma_write_buffer(device_parent(me),
53				buf,
54				0 /*address-space*/,
55				addr+count,
56				inc /*nr-bytes*/,
57				1 /*violate ro*/) != inc) {
58      fclose(image);
59      return -1;
60    }
61    count += inc;
62  }
63
64  /* close down again */
65  fclose(image);
66
67  return count;
68}
69
70
71/* DEVICE
72
73   file - load a file into memory
74
75   DESCRIPTION
76
77   Loads the entire contents of <file-name> into memory at starting at
78   <<real-address>>.  Assumes that memory exists for the load.
79
80   PROPERTIES
81
82   file-name = <string>
83
84   Name of the file to be loaded into memory
85
86   real-address = <integer>
87
88   Real address at which the file is to be loaded */
89
90static void
91hw_file_init_data_callback(device *me)
92{
93  int count;
94  const char *file_name = device_find_string_property(me, "file-name");
95  unsigned_word addr = device_find_integer_property(me, "real-address");
96  /* load the file */
97  count = dma_file(me, file_name, addr);
98  if (count < 0)
99    device_error(me, "Problem loading file %s\n", file_name);
100}
101
102
103static device_callbacks const hw_file_callbacks = {
104  { NULL, hw_file_init_data_callback, },
105  { NULL, }, /* address */
106  { NULL, }, /* IO */
107  { NULL, }, /* DMA */
108  { NULL, }, /* interrupt */
109  { NULL, }, /* unit */
110};
111
112
113/* DEVICE
114
115
116   data - initialize a memory location with specified data
117
118
119   DESCRIPTION
120
121
122   The pseudo device <<data>> provides a mechanism specifying the
123   initialization of a small section of memory.
124
125   Normally, the data would be written using a dma operation.
126   However, for some addresses this will not result in the desired
127   result.  For instance, to initialize an address in an eeprom,
128   instead of a simple dma of the data, a sequence of writes (and then
129   real delays) that program the eeprom would be required.
130
131   For dma write initialization, the data device will write the
132   specified <<data>> to <<real-address>> using a normal dma.
133
134   For instance write initialization, the specified <<instance>> is
135   opened.  Then a seek to the <<real-address>> is performed followed
136   by a write of the data.
137
138
139   Integer properties are stored using the target's endian mode.
140
141
142   PROPERTIES
143
144
145   data = <any-valid-property> (required)
146
147   Data to be loaded into memory.  The property type determines how it
148   is loaded.
149
150
151   real-address = <integer> (required)
152
153   Start address at which the data is to be stored.
154
155
156   instance = <string> (optional)
157
158   Instance specification of the device that is to be opened so that
159   the specified data can be written to it.
160
161
162   EXAMPLES
163
164
165   The examples below illustrate the two alternative mechanisms that
166   can be used to store the value 0x12345678 at address 0xfff00c00,
167   which is normally part of the 512k system eeprom.
168
169
170   If the eeprom is being modeled by ram (<<memory>> device) then the
171   standard dma initialization can be used.  By convention: the data
172   devices are uniquely identified by argumenting them with the
173   destinations real address; and all data devices are put under the
174   node <</openprom/init>>.
175
176   | /openprom/memory@0xfff00000/reg 0xfff00000 0x80000
177   | /openprom/init/data@0x1000/data 0x12345678
178   | /openprom/init/data@0x1000/real-address 0x1000
179
180
181   If instead a real eeprom was being used the instance write method
182   would instead need to be used (storing just a single byte in an
183   eeprom requires a complex sequence of accesses).  The
184   <<real-address>> is specified as <<0x0c00>> which is the offset
185   into the eeprom.  For brevity, most of the eeprom properties have
186   been omited.
187
188   | /iobus/eeprom@0xfff00000/reg 0xfff00000 0x80000
189   | /openprom/init/data@0xfff00c00/real-address 0x0c00
190   | /openprom/init/data@0xfff00c00/data 0x12345667
191   | /openprom/init/data@0xfff00c00/instance /iobus/eeprom@0xfff00000/reg
192
193
194   BUGS
195
196
197   At present, only <<integer>> properties can be specified for an
198   initial data value.
199
200   */
201
202
203static void
204hw_data_init_data_callback(device *me)
205{
206  unsigned_word addr = device_find_integer_property(me, "real-address");
207  const device_property *data = device_find_property(me, "data");
208  const char *instance_spec = (device_find_property(me, "instance") != NULL
209			       ? device_find_string_property(me, "instance")
210			       : NULL);
211  device_instance *instance = NULL;
212  if (data == NULL)
213    device_error(me, "missing property <data>\n");
214  if (instance_spec != NULL)
215    instance = tree_instance(me, instance_spec);
216  switch (data->type) {
217  case integer_property:
218    {
219      unsigned_cell buf = device_find_integer_property(me, "data");
220      H2T(buf);
221      if (instance == NULL) {
222	if (device_dma_write_buffer(device_parent(me),
223				    &buf,
224				    0 /*address-space*/,
225				    addr,
226				    sizeof(buf), /*nr-bytes*/
227				    1 /*violate ro*/) != sizeof(buf))
228	  device_error(me, "Problem storing integer 0x%x at 0x%lx\n",
229		       (unsigned)buf, (unsigned long)addr);
230      }
231      else {
232	if (device_instance_seek(instance, 0, addr) < 0
233	    || device_instance_write(instance, &buf, sizeof(buf)) != sizeof(buf))
234	  device_error(me, "Problem storing integer 0x%x at 0x%lx of instance %s\n",
235		       (unsigned)buf, (unsigned long)addr, instance_spec);
236      }
237    }
238    break;
239  default:
240    device_error(me, "Write of this data is not yet implemented\n");
241    break;
242  }
243  if (instance != NULL)
244    device_instance_delete(instance);
245}
246
247
248static device_callbacks const hw_data_callbacks = {
249  { NULL, hw_data_init_data_callback, },
250  { NULL, }, /* address */
251  { NULL, }, /* IO */
252  { NULL, }, /* DMA */
253  { NULL, }, /* interrupt */
254  { NULL, }, /* unit */
255};
256
257
258/* DEVICE
259
260
261   load-binary - load binary segments into memory
262
263
264   DESCRIPTION
265
266   Each loadable segment of the specified binary is loaded into memory
267   at its required address.  It is assumed that the memory at those
268   addresses already exists.
269
270   This device is normally used to load an executable into memory as
271   part of real mode simulation.
272
273
274   PROPERTIES
275
276
277   file-name = <string>
278
279   Name of the binary to be loaded.
280
281
282   claim = <anything> (optional)
283
284   If this property is present, the real memory that is to be used by
285   the image being loaded will be claimed from the memory node
286   (specified by the ihandle <</chosen/memory>>).
287
288
289   BUGS
290
291
292   When loading the binary the bfd virtual-address is used.  It should
293   be using the bfd load-address.
294
295   */
296
297/* DEVICE
298
299   map-binary - map the binary into the users address space
300
301   DESCRIPTION
302
303   Similar to load-binary except that memory for each segment is
304   created before the corresponding data for the segment is loaded.
305
306   This device is normally used to load an executable into a user mode
307   simulation.
308
309   PROPERTIES
310
311   file-name = <string>
312
313   Name of the binary to be loaded.
314
315   */
316
317static void
318update_for_binary_section(bfd *abfd,
319			  asection *the_section,
320			  PTR obj)
321{
322  unsigned_word section_vma;
323  unsigned_word section_size;
324  access_type access;
325  device *me = (device*)obj;
326
327  /* skip the section if no memory to allocate */
328  if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
329    return;
330
331  /* check/ignore any sections of size zero */
332  section_size = bfd_get_section_size (the_section);
333  if (section_size == 0)
334    return;
335
336  /* find where it is to go */
337  section_vma = bfd_get_section_vma(abfd, the_section);
338
339  DTRACE(binary,
340	 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
341	  bfd_get_section_name(abfd, the_section),
342	  (long)section_vma,
343	  (long)section_size,
344	  (long)bfd_get_section_flags(abfd, the_section),
345	  bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
346	  bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
347	  bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
348	  bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
349	  bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
350	  ));
351
352  /* If there is an .interp section, it means it needs a shared library interpreter.  */
353  if (strcmp(".interp", bfd_get_section_name(abfd, the_section)) == 0)
354    error("Shared libraries are not yet supported.\n");
355
356  /* determine the devices access */
357  access = access_read;
358  if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
359    access |= access_exec;
360  if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
361    access |= access_write;
362
363  /* if claim specified, allocate region from the memory device */
364  if (device_find_property(me, "claim") != NULL) {
365    device_instance *memory = tree_find_ihandle_property(me, "/chosen/memory");
366    unsigned_cell mem_in[3];
367    unsigned_cell mem_out[1];
368    mem_in[0] = 0; /*alignment - top-of-stack*/
369    mem_in[1] = section_size;
370    mem_in[2] = section_vma;
371    if (device_instance_call_method(memory, "claim", 3, mem_in, 1, mem_out) < 0)
372      device_error(me, "failed to claim memory for section at 0x%lx (0x%lx",
373		   section_vma,
374		   section_size);
375    if (mem_out[0] != section_vma)
376      device_error(me, "section address not as requested");
377  }
378
379  /* if a map, pass up a request to create the memory in core */
380  if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
381    device_attach_address(device_parent(me),
382			  attach_raw_memory,
383			  0 /*address space*/,
384			  section_vma,
385			  section_size,
386			  access,
387			  me);
388
389  /* if a load dma in the required data */
390  if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
391    void *section_init = zalloc(section_size);
392    if (!bfd_get_section_contents(abfd,
393				  the_section,
394				  section_init, 0,
395				  section_size)) {
396      bfd_perror("binary");
397      device_error(me, "load of data failed");
398      return;
399    }
400    if (device_dma_write_buffer(device_parent(me),
401				section_init,
402				0 /*space*/,
403				section_vma,
404				section_size,
405				1 /*violate_read_only*/)
406	!= section_size)
407      device_error(me, "broken transfer\n");
408    zfree(section_init); /* only free if load */
409  }
410}
411
412static void
413hw_binary_init_data_callback(device *me)
414{
415  /* get the file name */
416  const char *file_name = device_find_string_property(me, "file-name");
417  bfd *image;
418
419  /* open the file */
420  image = bfd_openr(file_name, NULL);
421  if (image == NULL) {
422    bfd_perror("binary");
423    device_error(me, "Failed to open file %s\n", file_name);
424  }
425
426  /* check it is valid */
427  if (!bfd_check_format(image, bfd_object)) {
428    bfd_close(image);
429    device_error(me, "The file %s has an invalid binary format\n", file_name);
430  }
431
432  /* and the data sections */
433  bfd_map_over_sections(image,
434			update_for_binary_section,
435			(PTR)me);
436
437  bfd_close(image);
438}
439
440
441static device_callbacks const hw_binary_callbacks = {
442  { NULL, hw_binary_init_data_callback, },
443  { NULL, }, /* address */
444  { NULL, }, /* IO */
445  { NULL, }, /* DMA */
446  { NULL, }, /* interrupt */
447  { NULL, }, /* unit */
448};
449
450
451/* DEVICE
452
453   stack - create an initial stack frame in memory
454
455   DESCRIPTION
456
457   Creates a stack frame of the specified type in memory.
458
459   Due to the startup sequence gdb uses when commencing a simulation,
460   it is not possible for the data to be placed on the stack to be
461   specified as part of the device tree.  Instead the arguments to be
462   pushed onto the stack are specified using an IOCTL call.
463
464   The IOCTL takes the additional arguments:
465
466   | unsigned_word stack_end -- where the stack should come down from
467   | char **argv -- ...
468   | char **envp -- ...
469
470   PROPERTIES
471
472   stack-type = <string>
473
474   The form of the stack frame that is to be created.
475
476   */
477
478static int
479sizeof_argument_strings(char **arg)
480{
481  int sizeof_strings = 0;
482
483  /* robust */
484  if (arg == NULL)
485    return 0;
486
487  /* add up all the string sizes (padding as we go) */
488  for (; *arg != NULL; arg++) {
489    int len = strlen(*arg) + 1;
490    sizeof_strings += ALIGN_8(len);
491  }
492
493  return sizeof_strings;
494}
495
496static int
497number_of_arguments(char **arg)
498{
499  int nr;
500  if (arg == NULL)
501    return 0;
502  for (nr = 0; *arg != NULL; arg++, nr++);
503  return nr;
504}
505
506static int
507sizeof_arguments(char **arg)
508{
509  return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
510}
511
512static void
513write_stack_arguments(device *me,
514		      char **arg,
515		      unsigned_word start_block,
516		      unsigned_word end_block,
517		      unsigned_word start_arg,
518		      unsigned_word end_arg)
519{
520  DTRACE(stack,
521	("write_stack_arguments(device=%s, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
522	 device_name(me), (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
523  if (arg == NULL)
524    device_error(me, "Attempt to write a null array onto the stack\n");
525  /* only copy in arguments, memory is already zero */
526  for (; *arg != NULL; arg++) {
527    int len = strlen(*arg)+1;
528    unsigned_word target_start_block;
529    DTRACE(stack,
530	  ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
531	   "**arg", *arg, "start_block", (long)start_block,
532	   "len", (long)len, "start_arg", (long)start_arg));
533    if (psim_write_memory(device_system(me), 0, *arg,
534			  start_block, len,
535			  0/*violate_readonly*/) != len)
536      device_error(me, "Write of **arg (%s) at 0x%lx of stack failed\n",
537		   *arg, (unsigned long)start_block);
538    target_start_block = H2T_word(start_block);
539    if (psim_write_memory(device_system(me), 0, &target_start_block,
540			  start_arg, sizeof(target_start_block),
541			  0) != sizeof(target_start_block))
542      device_error(me, "Write of *arg onto stack failed\n");
543    start_block += ALIGN_8(len);
544    start_arg += sizeof(start_block);
545  }
546  start_arg += sizeof(start_block); /*the null at the end*/
547  if (start_block != end_block
548      || ALIGN_8(start_arg) != end_arg)
549    device_error(me, "Probable corrpution of stack arguments\n");
550  DTRACE(stack, ("write_stack_arguments() = void\n"));
551}
552
553static void
554create_ppc_elf_stack_frame(device *me,
555			   unsigned_word bottom_of_stack,
556			   char **argv,
557			   char **envp)
558{
559  /* fixme - this is over aligned */
560
561  /* information block */
562  const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
563  const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
564  const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
565  const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
566
567  /* auxiliary vector - contains only one entry */
568  const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
569  const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
570
571  /* environment points (including null sentinal) */
572  const unsigned sizeof_envp = sizeof_arguments(envp);
573  const unsigned_word start_envp = start_aux - sizeof_envp;
574
575  /* argument pointers (including null sentinal) */
576  const int argc = number_of_arguments(argv);
577  const unsigned sizeof_argv = sizeof_arguments(argv);
578  const unsigned_word start_argv = start_envp - sizeof_argv;
579
580  /* link register save address - alligned to a 16byte boundary */
581  const unsigned_word top_of_stack = ((start_argv
582				       - 2 * sizeof(unsigned_word))
583				      & ~0xf);
584
585  /* install arguments on stack */
586  write_stack_arguments(me, envp,
587			start_envp_block, bottom_of_stack,
588			start_envp, start_aux);
589  write_stack_arguments(me, argv,
590			start_argv_block, start_envp_block,
591			start_argv, start_envp);
592
593  /* set up the registers */
594  ASSERT (psim_write_register(device_system(me), -1,
595			      &top_of_stack, "sp", cooked_transfer) > 0);
596  ASSERT (psim_write_register(device_system(me), -1,
597			      &argc, "r3", cooked_transfer) > 0);
598  ASSERT (psim_write_register(device_system(me), -1,
599			      &start_argv, "r4", cooked_transfer) > 0);
600  ASSERT (psim_write_register(device_system(me), -1,
601			      &start_envp, "r5", cooked_transfer) > 0);
602  ASSERT (psim_write_register(device_system(me), -1,
603			      &start_aux, "r6", cooked_transfer) > 0);
604}
605
606static void
607create_ppc_aix_stack_frame(device *me,
608			   unsigned_word bottom_of_stack,
609			   char **argv,
610			   char **envp)
611{
612  unsigned_word core_envp;
613  unsigned_word core_argv;
614  unsigned_word core_argc;
615  unsigned_word core_aux;
616  unsigned_word top_of_stack;
617
618  /* cheat - create an elf stack frame */
619  create_ppc_elf_stack_frame(me, bottom_of_stack, argv, envp);
620
621  /* extract argument addresses from registers */
622  ASSERT (psim_read_register(device_system(me), 0,
623			     &top_of_stack, "r1", cooked_transfer) > 0);
624  ASSERT (psim_read_register(device_system(me), 0,
625			     &core_argc, "r3", cooked_transfer) > 0);
626  ASSERT (psim_read_register(device_system(me), 0,
627			     &core_argv, "r4", cooked_transfer) > 0);
628  ASSERT (psim_read_register(device_system(me), 0,
629			     &core_envp, "r5", cooked_transfer) > 0);
630  ASSERT (psim_read_register(device_system(me), 0,
631			     &core_aux, "r6", cooked_transfer) > 0);
632
633  /* extract arguments from registers */
634  device_error(me, "Unfinished procedure create_ppc_aix_stack_frame\n");
635}
636
637
638static void
639create_ppc_chirp_bootargs(device *me,
640			  char **argv)
641{
642  /* concat the arguments */
643  char args[1024];
644  char **chp = argv + 1;
645  args[0] = '\0';
646  while (*chp != NULL) {
647    if (strlen(args) > 0)
648      strcat(args, " ");
649    if (strlen(args) + strlen(*chp) >= sizeof(args))
650      device_error(me, "buffer overflow");
651    strcat(args, *chp);
652    chp++;
653  }
654
655  /* set the arguments property */
656  tree_parse(me, "/chosen/bootargs \"%s", args);
657}
658
659
660static int
661hw_stack_ioctl(device *me,
662	       cpu *processor,
663	       unsigned_word cia,
664	       device_ioctl_request request,
665	       va_list ap)
666{
667  switch (request) {
668  case device_ioctl_create_stack:
669    {
670      unsigned_word stack_pointer = va_arg(ap, unsigned_word);
671      char **argv = va_arg(ap, char **);
672      char **envp = va_arg(ap, char **);
673      const char *stack_type;
674      DTRACE(stack,
675	     ("stack_ioctl_callback(me=0x%lx:%s processor=0x%lx cia=0x%lx argv=0x%lx envp=0x%lx)\n",
676	      (long)me, device_name(me),
677	      (long)processor,
678	      (long)cia,
679	      (long)argv,
680	      (long)envp));
681      stack_type = device_find_string_property(me, "stack-type");
682      if (strcmp(stack_type, "ppc-elf") == 0)
683	create_ppc_elf_stack_frame(me, stack_pointer, argv, envp);
684      else if (strcmp(stack_type, "ppc-xcoff") == 0)
685	create_ppc_aix_stack_frame(me, stack_pointer, argv, envp);
686      else if (strcmp(stack_type, "chirp") == 0)
687	create_ppc_chirp_bootargs(me, argv);
688      else if (strcmp(stack_type, "none") != 0)
689	device_error(me, "Unknown initial stack frame type %s", stack_type);
690      DTRACE(stack,
691	     ("stack_ioctl_callback() = void\n"));
692      break;
693    }
694  default:
695    device_error(me, "Unsupported ioctl requested");
696    break;
697  }
698  return 0;
699}
700
701static device_callbacks const hw_stack_callbacks = {
702  { NULL, },
703  { NULL, }, /* address */
704  { NULL, }, /* IO */
705  { NULL, }, /* DMA */
706  { NULL, }, /* interrupt */
707  { NULL, }, /* unit */
708  NULL, /* instance */
709  hw_stack_ioctl,
710};
711
712const device_descriptor hw_init_device_descriptor[] = {
713  { "file", NULL, &hw_file_callbacks },
714  { "data", NULL, &hw_data_callbacks },
715  { "load-binary", NULL, &hw_binary_callbacks },
716  { "map-binary", NULL, &hw_binary_callbacks },
717  { "stack", NULL, &hw_stack_callbacks },
718  { NULL },
719};
720
721#endif /* _HW_INIT_C_ */
722