INLINE_EMUL_GENERIC void emul_add_tree_options(device *tree, bfd *image, const char *emul, const char *env, int oea_interrupt_prefix) { int little_endian = 0; /* sort out little endian */ if (tree_find_property(tree, "/options/little-endian?")) little_endian = tree_find_boolean_property(tree, "/options/little-endian?"); else { #ifdef bfd_little_endian /* new bfd */ little_endian = (image != NULL && bfd_little_endian(image)); #else little_endian = (image != NULL && !image->xvec->byteorder_big_p); #endif tree_parse(tree, "/options/little-endian? %s", little_endian ? "true" : "false"); } /* misc other stuff */ tree_parse(tree, "/openprom/options/oea-memory-size 0x%x", OEA_MEMORY_SIZE); tree_parse(tree, "/openprom/options/oea-interrupt-prefix %d", oea_interrupt_prefix); tree_parse(tree, "/openprom/options/smp 1"); tree_parse(tree, "/openprom/options/env %s", env); tree_parse(tree, "/openprom/options/os-emul %s", emul); tree_parse(tree, "/openprom/options/strict-alignment? %s", (WITH_ALIGNMENT == STRICT_ALIGNMENT) ? "true" : "false"); tree_parse(tree, "/openprom/options/floating-point? %s", WITH_FLOATING_POINT ? "true" : "false"); tree_parse(tree, "/openprom/options/use-stdio? %s", ((WITH_STDIO == DO_USE_STDIO || WITH_STDIO == 0) ? "true" : "false")); tree_parse(tree, "/openprom/options/model \"%s", model_name[WITH_DEFAULT_MODEL]); tree_parse(tree, "/openprom/options/model-issue %d", MODEL_ISSUE_IGNORE); /* useful options */ }
psim_init(psim *system) { int cpu_nr; /* scrub the monitor */ mon_init(system->monitor, system->nr_cpus); /* trash any pending events */ event_queue_init(system->events); /* if needed, schedule a halt event. FIXME - In the future this will be replaced by a more generic change to psim_command(). A new command `schedule NNN halt' being added. */ if (tree_find_property(system->devices, "/openprom/options/max-iterations")) { event_queue_schedule(system->events, tree_find_integer_property(system->devices, "/openprom/options/max-iterations") - 2, psim_max_iterations_exceeded, system); } /* scrub all the cpus */ for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) cpu_init(system->processors[cpu_nr]); /* init all the devices (which updates the cpus) */ tree_init(system->devices, system); /* and the emulation (which needs an initialized device tree) */ os_emul_init(system->os_emulation, system->nr_cpus); /* now sync each cpu against the initialized state of its registers */ for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) { cpu *processor = system->processors[cpu_nr]; cpu_synchronize_context(processor, cpu_get_program_counter(processor)); cpu_page_tlb_invalidate_all(processor); } /* force loop to start with first cpu */ system->last_cpu = -1; }
static void emul_bugapi_init(os_emul_data *bugapi, int nr_cpus) { int i; /* get the current input/output devices that were created during device tree initialization */ bugapi->input = tree_find_ihandle_property(bugapi->root, "/chosen/stdin"); bugapi->output = tree_find_ihandle_property(bugapi->root, "/chosen/stdout"); /* if present, extract the selected disk devices */ for (i = 0; i < nr_bugapi_disks; i++) { char disk[32]; char *chp; strcpy(disk, "/chosen/disk0"); ASSERT(sizeof(disk) > strlen(disk)); chp = strchr(disk, '0'); *chp = *chp + i; if (tree_find_property(bugapi->root, disk) != NULL) bugapi->disk[i] = tree_find_ihandle_property(bugapi->root, disk); } }
tree_parse(device *current, const char *fmt, ...) { char device_specifier[1024]; name_specifier spec; /* format the path */ { va_list ap; va_start(ap, fmt); vsprintf(device_specifier, fmt, ap); va_end(ap); if (strlen(device_specifier) >= sizeof(device_specifier)) error("device_tree_add_deviced: buffer overflow\n"); } /* construct the tree down to the final device */ current = split_fill_path(current, device_specifier, &spec); /* is there an interrupt spec */ if (spec.property == NULL && spec.value != NULL) { char *op = split_value(&spec); switch (op[0]) { case '>': { char *my_port_name = split_value(&spec); int my_port; char *dest_port_name = split_value(&spec); int dest_port; name_specifier dest_spec; char *dest_device_name = split_value(&spec); device *dest; /* find my name */ my_port = device_interrupt_decode(current, my_port_name, output_port); /* find the dest device and port */ dest = split_fill_path(current, dest_device_name, &dest_spec); dest_port = device_interrupt_decode(dest, dest_port_name, input_port); /* connect the two */ device_interrupt_attach(current, my_port, dest, dest_port, permenant_object); } break; default: device_error(current, "unreconised interrupt spec %s\n", spec.value); break; } } /* is there a property */ if (spec.property != NULL) { if (strcmp(spec.value, "true") == 0) device_add_boolean_property(current, spec.property, 1); else if (strcmp(spec.value, "false") == 0) device_add_boolean_property(current, spec.property, 0); else { const device_property *property; switch (spec.value[0]) { case '*': parse_ihandle_property(current, spec.property, spec.value + 1); break; case '[': { unsigned8 words[1024]; char *curr = spec.value + 1; int nr_words = 0; while (1) { char *next; words[nr_words] = H2BE_1(strtoul(curr, &next, 0)); if (curr == next) break; curr = next; nr_words += 1; } device_add_array_property(current, spec.property, words, sizeof(words[0]) * nr_words); } break; case '"': parse_string_property(current, spec.property, spec.value); break; case '!': spec.value++; property = tree_find_property(current, spec.value); if (property == NULL) device_error(current, "property %s not found\n", spec.value); device_add_duplicate_property(current, spec.property, property); break; default: if (strcmp(spec.property, "reg") == 0 || strcmp(spec.property, "assigned-addresses") == 0 || strcmp(spec.property, "alternate-reg") == 0){ parse_reg_property(current, spec.property, spec.value); } else if (strcmp(spec.property, "ranges") == 0) { parse_ranges_property(current, spec.property, spec.value); } else if (isdigit(spec.value[0]) || (spec.value[0] == '-' && isdigit(spec.value[1])) || (spec.value[0] == '+' && isdigit(spec.value[1]))) { parse_integer_property(current, spec.property, spec.value); } else parse_string_property(current, spec.property, spec.value); break; } } } return current; }