Replace accidentally broken configure from previous regenerate.
[deliverable/binutils-gdb.git] / sim / ppc / hw_init.c
CommitLineData
c906108c
SS
1/* This file is part of the program psim.
2
dcb74f96 3 Copyright 1994, 1997, 2003, 2004 Andrew Cagney
c906108c
SS
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);
d4481806 50 if (inc <= 0)
c906108c
SS
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 */
dcb74f96 332 section_size = bfd_get_section_size (the_section);
c906108c
SS
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 */
601cecf0
AC
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);
c906108c
SS
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 */
601cecf0
AC
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);
c906108c
SS
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_
This page took 0.319202 seconds and 4 git commands to generate.