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