1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
25 #include "device_table.h"
30 /* DMA a file into memory */
33 const char *file_name
,
42 image
= fopen(file_name
, "r");
46 /* read it in slowly */
49 inc
= fread(buf
, 1, sizeof(buf
), image
);
50 if (feof(image
) || ferror(image
))
52 if (device_dma_write_buffer(device_parent(me
),
57 1 /*violate ro*/) != inc
) {
64 /* close down again */
73 file - load a file into memory
77 Loads the entire contents of <file-name> into memory at starting at
78 <real-address>. Assumes that memory exists for the load.
84 Name of the file to be loaded into memory
86 real-address = <integer>
88 Real address at which the file is to be loaded */
91 hw_file_init_data_callback(device
*me
)
94 const char *file_name
= device_find_string_property(me
, "file-name");
95 unsigned_word addr
= device_find_integer_property(me
, "real-address");
97 count
= dma_file(me
, file_name
, addr
);
99 device_error(me
, "Problem loading file %s\n", file_name
);
103 static device_callbacks
const hw_file_callbacks
= {
104 { NULL
, hw_file_init_data_callback
, },
105 { NULL
, }, /* address */
108 { NULL
, }, /* interrupt */
109 { NULL
, }, /* unit */
115 data - initialize a memory location
119 A word sized quantity of data is written into memory, using the
120 targets byte ordering, at the specified memory location.
122 In the future this device will be extended so that it supports
123 initialization using other data types (eg array, ...)
129 Integer value to be loaded into memory
131 real-address = <integer>
133 Start address for the data. */
137 hw_data_init_data_callback(device
*me
)
139 unsigned_word addr
= device_find_integer_property(me
, "real-address");
140 const device_property
*data
= device_find_property(me
, "data");
142 device_error(me
, "missing property <data>\n");
143 switch (data
->type
) {
144 case integer_property
:
146 unsigned32 buf
= device_find_integer_property(me
, "data");
148 if (device_dma_write_buffer(device_parent(me
),
152 sizeof(buf
), /*nr-bytes*/
153 1 /*violate ro*/) != sizeof(buf
))
154 device_error(me
, "Problem storing integer 0x%x at 0x%lx\n",
155 (unsigned)buf
, (unsigned long)addr
);
159 device_error(me
, "Write of this data is not yet implemented\n");
165 static device_callbacks
const hw_data_callbacks
= {
166 { NULL
, hw_data_init_data_callback
, },
167 { NULL
, }, /* address */
170 { NULL
, }, /* interrupt */
171 { NULL
, }, /* unit */
177 load-binary - load binary segments into memory
181 Each loadable segment of the specified binary is loaded into memory
182 at its required address. It is assumed that the memory at those
183 addresses already exists.
185 This device is normally used to load an executable into memory as
186 part of real mode simulation.
192 Name of the binary to be loaded.
196 map-binary - map the binary into the users address space
200 Similar to load-binary except that memory for each segment is
201 created before the corresponding data for the segment is loaded.
203 This device is normally used to load an executable into a user mode
210 Name of the binary to be loaded.
215 update_for_binary_section(bfd
*abfd
,
216 asection
*the_section
,
219 unsigned_word section_vma
;
220 unsigned_word section_size
;
222 device
*me
= (device
*)obj
;
224 /* skip the section if no memory to allocate */
225 if (! (bfd_get_section_flags(abfd
, the_section
) & SEC_ALLOC
))
228 /* check/ignore any sections of size zero */
229 section_size
= bfd_get_section_size_before_reloc(the_section
);
230 if (section_size
== 0)
233 /* find where it is to go */
234 section_vma
= bfd_get_section_vma(abfd
, the_section
);
237 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
238 bfd_get_section_name(abfd
, the_section
),
241 (long)bfd_get_section_flags(abfd
, the_section
),
242 bfd_get_section_flags(abfd
, the_section
) & SEC_LOAD
? " LOAD" : "",
243 bfd_get_section_flags(abfd
, the_section
) & SEC_CODE
? " CODE" : "",
244 bfd_get_section_flags(abfd
, the_section
) & SEC_DATA
? " DATA" : "",
245 bfd_get_section_flags(abfd
, the_section
) & SEC_ALLOC
? " ALLOC" : "",
246 bfd_get_section_flags(abfd
, the_section
) & SEC_READONLY
? " READONLY" : ""
249 /* If there is an .interp section, it means it needs a shared library interpreter. */
250 if (strcmp(".interp", bfd_get_section_name(abfd
, the_section
)) == 0)
251 error("Shared libraries are not yet supported.\n");
253 /* determine the devices access */
254 access
= access_read
;
255 if (bfd_get_section_flags(abfd
, the_section
) & SEC_CODE
)
256 access
|= access_exec
;
257 if (!(bfd_get_section_flags(abfd
, the_section
) & SEC_READONLY
))
258 access
|= access_write
;
260 /* if a map, pass up a request to create the memory in core */
261 if (strncmp(device_name(me
), "map-binary", strlen("map-binary")) == 0)
262 device_attach_address(device_parent(me
),
271 /* if a load dma in the required data */
272 if (bfd_get_section_flags(abfd
, the_section
) & SEC_LOAD
) {
273 void *section_init
= zalloc(section_size
);
274 if (!bfd_get_section_contents(abfd
,
278 bfd_perror("binary");
279 device_error(me
, "load of data failed");
282 if (device_dma_write_buffer(device_parent(me
),
287 1 /*violate_read_only*/)
289 device_error(me
, "broken transfer\n");
290 zfree(section_init
); /* only free if load */
295 hw_binary_init_data_callback(device
*me
)
297 /* get the file name */
298 const char *file_name
= device_find_string_property(me
, "file-name");
302 image
= bfd_openr(file_name
, NULL
);
304 bfd_perror("binary");
305 device_error(me
, "Failed to open file %s\n", file_name
);
308 /* check it is valid */
309 if (!bfd_check_format(image
, bfd_object
)) {
311 device_error(me
, "The file %s has an invalid binary format\n", file_name
);
314 /* and the data sections */
315 bfd_map_over_sections(image
,
316 update_for_binary_section
,
323 static device_callbacks
const hw_binary_callbacks
= {
324 { NULL
, hw_binary_init_data_callback
, },
325 { NULL
, }, /* address */
328 { NULL
, }, /* interrupt */
329 { NULL
, }, /* unit */
335 stack - create an initial stack frame in memory
339 Creates a stack frame of the specified type in memory.
341 Due to the startup sequence gdb uses when commencing a simulation,
342 it is not possible for the data to be placed on the stack to be
343 specified as part of the device tree. Instead the arguments to be
344 pushed onto the stack are specified using an IOCTL call.
346 The IOCTL takes the additional arguments:
348 | unsigned_word stack_end -- where the stack should come down from
354 stack-type = <string>
356 The form of the stack frame that is to be created.
361 sizeof_argument_strings(char **arg
)
363 int sizeof_strings
= 0;
369 /* add up all the string sizes (padding as we go) */
370 for (; *arg
!= NULL
; arg
++) {
371 int len
= strlen(*arg
) + 1;
372 sizeof_strings
+= ALIGN_8(len
);
375 return sizeof_strings
;
379 number_of_arguments(char **arg
)
384 for (nr
= 0; *arg
!= NULL
; arg
++, nr
++);
389 sizeof_arguments(char **arg
)
391 return ALIGN_8((number_of_arguments(arg
) + 1) * sizeof(unsigned_word
));
395 write_stack_arguments(device
*me
,
397 unsigned_word start_block
,
398 unsigned_word end_block
,
399 unsigned_word start_arg
,
400 unsigned_word end_arg
)
403 ("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",
404 device_name(me
), (long)arg
, (long)start_block
, (long)end_block
, (long)start_arg
, (long)end_arg
));
406 device_error(me
, "Attempt to write a null array onto the stack\n");
407 /* only copy in arguments, memory is already zero */
408 for (; *arg
!= NULL
; arg
++) {
409 int len
= strlen(*arg
)+1;
410 unsigned_word target_start_block
;
412 ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
413 "**arg", *arg
, "start_block", (long)start_block
,
414 "len", (long)len
, "start_arg", (long)start_arg
));
415 if (psim_write_memory(device_system(me
), 0, *arg
,
417 0/*violate_readonly*/) != len
)
418 device_error(me
, "Write of **arg (%s) at 0x%lx of stack failed\n",
419 *arg
, (unsigned long)start_block
);
420 target_start_block
= H2T_word(start_block
);
421 if (psim_write_memory(device_system(me
), 0, &target_start_block
,
422 start_arg
, sizeof(target_start_block
),
423 0) != sizeof(target_start_block
))
424 device_error(me
, "Write of *arg onto stack failed\n");
425 start_block
+= ALIGN_8(len
);
426 start_arg
+= sizeof(start_block
);
428 start_arg
+= sizeof(start_block
); /*the null at the end*/
429 if (start_block
!= end_block
430 || ALIGN_8(start_arg
) != end_arg
)
431 device_error(me
, "Probable corrpution of stack arguments\n");
432 DTRACE(stack
, ("write_stack_arguments() = void\n"));
436 create_ppc_elf_stack_frame(device
*me
,
437 unsigned_word bottom_of_stack
,
441 /* fixme - this is over aligned */
443 /* information block */
444 const unsigned sizeof_envp_block
= sizeof_argument_strings(envp
);
445 const unsigned_word start_envp_block
= bottom_of_stack
- sizeof_envp_block
;
446 const unsigned sizeof_argv_block
= sizeof_argument_strings(argv
);
447 const unsigned_word start_argv_block
= start_envp_block
- sizeof_argv_block
;
449 /* auxiliary vector - contains only one entry */
450 const unsigned sizeof_aux_entry
= 2*sizeof(unsigned_word
); /* magic */
451 const unsigned_word start_aux
= start_argv_block
- ALIGN_8(sizeof_aux_entry
);
453 /* environment points (including null sentinal) */
454 const unsigned sizeof_envp
= sizeof_arguments(envp
);
455 const unsigned_word start_envp
= start_aux
- sizeof_envp
;
457 /* argument pointers (including null sentinal) */
458 const int argc
= number_of_arguments(argv
);
459 const unsigned sizeof_argv
= sizeof_arguments(argv
);
460 const unsigned_word start_argv
= start_envp
- sizeof_argv
;
462 /* link register save address - alligned to a 16byte boundary */
463 const unsigned_word top_of_stack
= ((start_argv
464 - 2 * sizeof(unsigned_word
))
467 /* install arguments on stack */
468 write_stack_arguments(me
, envp
,
469 start_envp_block
, bottom_of_stack
,
470 start_envp
, start_aux
);
471 write_stack_arguments(me
, argv
,
472 start_argv_block
, start_envp_block
,
473 start_argv
, start_envp
);
475 /* set up the registers */
476 psim_write_register(device_system(me
), -1,
477 &top_of_stack
, "sp", cooked_transfer
);
478 psim_write_register(device_system(me
), -1,
479 &argc
, "r3", cooked_transfer
);
480 psim_write_register(device_system(me
), -1,
481 &start_argv
, "r4", cooked_transfer
);
482 psim_write_register(device_system(me
), -1,
483 &start_envp
, "r5", cooked_transfer
);
484 psim_write_register(device_system(me
), -1,
485 &start_aux
, "r6", cooked_transfer
);
489 create_ppc_aix_stack_frame(device
*me
,
490 unsigned_word bottom_of_stack
,
494 unsigned_word core_envp
;
495 unsigned_word core_argv
;
496 unsigned_word core_argc
;
497 unsigned_word core_aux
;
498 unsigned_word top_of_stack
;
500 /* cheat - create an elf stack frame */
501 create_ppc_elf_stack_frame(me
, bottom_of_stack
, argv
, envp
);
503 /* extract argument addresses from registers */
504 psim_read_register(device_system(me
), 0,
505 &top_of_stack
, "r1", cooked_transfer
);
506 psim_read_register(device_system(me
), 0,
507 &core_argc
, "r3", cooked_transfer
);
508 psim_read_register(device_system(me
), 0,
509 &core_argv
, "r4", cooked_transfer
);
510 psim_read_register(device_system(me
), 0,
511 &core_envp
, "r5", cooked_transfer
);
512 psim_read_register(device_system(me
), 0,
513 &core_aux
, "r6", cooked_transfer
);
515 /* extract arguments from registers */
516 device_error(me
, "Unfinished procedure create_ppc_aix_stack_frame\n");
522 hw_stack_ioctl_callback(device
*me
,
527 unsigned_word stack_pointer
;
528 const char *stack_type
;
531 stack_pointer
= va_arg(ap
, unsigned_word
);
532 argv
= va_arg(ap
, char **);
533 envp
= va_arg(ap
, char **);
535 ("stack_ioctl_callback(me=0x%lx:%s processor=0x%lx cia=0x%lx argv=0x%lx envp=0x%lx)\n",
536 (long)me
, device_name(me
), (long)processor
, (long)cia
, (long)argv
, (long)envp
));
537 stack_type
= device_find_string_property(me
, "stack-type");
538 if (strcmp(stack_type
, "ppc-elf") == 0)
539 create_ppc_elf_stack_frame(me
, stack_pointer
, argv
, envp
);
540 else if (strcmp(stack_type
, "ppc-xcoff") == 0)
541 create_ppc_aix_stack_frame(me
, stack_pointer
, argv
, envp
);
542 else if (strcmp(stack_type
, "none") != 0)
543 device_error(me
, "Unknown initial stack frame type %s\n", stack_type
);
545 ("stack_ioctl_callback() = void\n"));
549 static device_callbacks
const hw_stack_callbacks
= {
551 { NULL
, }, /* address */
554 { NULL
, }, /* interrupt */
555 { NULL
, }, /* unit */
557 hw_stack_ioctl_callback
,
560 const device_descriptor hw_init_device_descriptor
[] = {
561 { "file", NULL
, &hw_file_callbacks
},
562 { "data", NULL
, &hw_data_callbacks
},
563 { "load-binary", NULL
, &hw_binary_callbacks
},
564 { "map-binary", NULL
, &hw_binary_callbacks
},
565 { "stack", NULL
, &hw_stack_callbacks
},