xref: /netbsd-src/external/gpl3/gdb/dist/sim/ppc/hw_init.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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 */
31 static int
32 dma_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 
90 static void
91 hw_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 
103 static 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 
203 static void
204 hw_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 
248 static 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 
317 static void
318 update_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     free(section_init); /* only free if load */
409   }
410 }
411 
412 static void
413 hw_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 
441 static 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 
478 static int
479 sizeof_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 
496 static int
497 number_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 
506 static int
507 sizeof_arguments(char **arg)
508 {
509   return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
510 }
511 
512 static void
513 write_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 
553 static void
554 create_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 
606 static void
607 create_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 
638 static void
639 create_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 
660 static int
661 hw_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 
701 static 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 
712 const 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