+ else
+ tree_parse(root, "/options/real-size 0x%lx",
+ (unsigned long)chirp->real_size);
+
+ /* resolve virt-base */
+ if (chirp->real_mode)
+ chirp->virt_base = chirp->real_base;
+ else if (note.found == note_correct && note.desc.virt_base != -1)
+ chirp->virt_base = note.desc.virt_base;
+ else if (tree_find_property(root, "/options/virt-base") != NULL)
+ chirp->virt_base = tree_find_integer_property(root, "/options/virt-base");
+ else
+ chirp->virt_base = CHIRP_START_ADDRESS;
+ if (tree_find_property(root, "/options/virt-base") != NULL) {
+ unsigned_word virt_base = tree_find_integer_property(root, "/options/virt-base");
+ if (virt_base != -1 && chirp->virt_base != virt_base)
+ error("chirp: /options/virt-base conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/virt-base 0x%lx",
+ chirp->real_mode ? -1 : (unsigned long)chirp->virt_base);
+
+ /* resolve virt-size */
+ chirp->virt_size = chirp->real_size;
+ if (note.found == note_correct
+ && note.desc.virt_size != (signed32)-1
+ && note.desc.virt_size != 0
+ && !chirp->real_mode
+ && chirp->virt_size > note.desc.virt_size)
+ error("chirp: insufficent virtual memory for firmware\n");
+ if (tree_find_property(root, "/options/virt-size") != NULL) {
+ if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size"))
+ error("chirp: /options/virt-size conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/virt-size 0x%lx",
+ chirp->real_mode ? -1 : (unsigned long)chirp->virt_size);
+
+ /* resolve load-base */
+ if (note.found == note_correct
+ && note.desc.load_base != (signed32)-1)
+ chirp->load_base = note.desc.load_base;
+ else if (tree_find_property(root, "/options/load-base") != NULL)
+ chirp->load_base = tree_find_integer_property(root, "/options/load-base");
+ else
+ chirp->load_base = CHIRP_LOAD_BASE;
+ if (tree_find_property(root, "/options/load-base") != NULL) {
+ if (chirp->load_base != tree_find_integer_property(root, "/options/load-base"))
+ error("chirp: /options/load-base conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/load-base 0x%lx",
+ (unsigned long)chirp->load_base);
+
+ /* now adjust the preliminary firmware addresses to final values */
+ chirp->code_ra = chirp->code_offset + chirp->real_base;
+ chirp->stack_ra = chirp->stack_offset + chirp->real_base;
+ chirp->htab_ra = chirp->htab_offset + chirp->real_base;
+
+ /* the virtual addresses. In real mode these are real addresses. */
+
+ chirp->code_va = chirp->code_offset + chirp->virt_base;
+ chirp->stack_va = chirp->stack_offset + chirp->virt_base;
+ chirp->htab_va = chirp->htab_offset + chirp->virt_base;
+
+ chirp->code_client_va = chirp->code_va;
+ chirp->code_client_ra = chirp->code_ra;
+
+ chirp->code_callback_va = chirp->code_client_va + 16;
+ chirp->code_callback_ra = chirp->code_client_ra + 16;
+
+ chirp->code_loop_va = chirp->code_callback_va + 16;
+ chirp->code_loop_ra = chirp->code_callback_ra + 16;
+
+ /* initialization */
+
+ tree_parse(root, "/openprom/init");
+ tree_parse(root, "/openprom/init/register");
+ tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
+ (unsigned long)bfd_get_start_address(image));
+ tree_parse(root, "/openprom/init/register/pc 0x%lx",
+ (unsigned long)chirp->code_loop_va);
+ tree_parse(root, "/openprom/init/register/msr 0x%x",
+ (msr_machine_check_enable
+ | (chirp->real_mode
+ ? 0
+ : (msr_instruction_relocate
+ | msr_data_relocate))
+ | (chirp->little_endian
+ ? (msr_little_endian_mode
+ | msr_interrupt_little_endian_mode)
+ : 0)
+ | (chirp->floating_point_available
+ ? msr_floating_point_available
+ : 0)
+ | (chirp->interrupt_prefix
+ ? msr_interrupt_prefix
+ : 0)
+ ));
+ tree_parse(root, "/openprom/init/register/sdr1 0x%lx",
+ (unsigned long)(chirp->htab_ra
+ | MASK32(16, 22)
+ | ((chirp->sizeof_htab - 1) >> 16)));
+ /* make certain that the segment registers map straight through */
+ for (i = 0; i < 16; i++) {
+ tree_parse(root, "/openprom/init/register/sr%d 0x%lx",
+ i, (unsigned long)i);
+ }
+
+ /* establish an initial state for all processors */
+
+
+ /* the client interface address */
+ tree_parse(root, "/openprom/init/register/r5 0x%lx",
+ (unsigned long)chirp->code_client_va);
+ /* a stack */
+ tree_parse(root, "/openprom/init/register/sp 0x%lx",
+ (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
+ /* in chrp mode any arguments end up being concatinated */
+ tree_parse(root, "/openprom/init/stack/stack-type chirp");
+
+
+ /* client interface - emul-call followed by return instruction */
+
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)chirp->code_client_ra);
+ tree_parse(node, "./psim,description \"client-interface instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_client_ra);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_call_instruction);
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)(chirp->code_client_ra + 4));
+ tree_parse(node, "./psim,description \"client-interface return instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)(chirp->code_client_ra + 4));
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_blr_instruction);
+
+
+ /* return address for client callbacks - an emul-call instruction
+ that is again followed by a return instruction */
+
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)chirp->code_callback_ra);
+ tree_parse(node, "./psim,description \"client-callback instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_callback_ra);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_call_instruction);
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)(chirp->code_callback_ra + 4));
+ tree_parse(node, "./psim,description \"client-callback return instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)(chirp->code_callback_ra + 4));
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_blr_instruction);
+
+ /* loop to keep other processors busy */
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)chirp->code_loop_ra);
+ tree_parse(node, "./psim,description \"processor busy loop");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_loop_ra);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_loop_instruction);
+
+ /* hash table */
+
+ /* create a hash table */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab@0x%lx",
+ (unsigned long)chirp->htab_ra);
+ tree_parse(node, "./claim 0");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->htab_ra);
+ tree_parse(node, "./nr-bytes 0x%lx",
+ (unsigned long)chirp->sizeof_htab);
+ }
+
+ /* map in the stack */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+ (unsigned long)chirp->stack_ra);
+ tree_parse(node, "./psim,description \"map in the stack");
+ tree_parse(node, "./claim 1");
+ tree_parse(node, "./virtual-address 0x%lx",
+ (unsigned long)chirp->stack_va);
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->stack_ra);
+ tree_parse(node, "./nr-bytes 0x%lx",
+ (unsigned long)chirp->sizeof_stack);
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
+ /* map in the chrp openboot callback code */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+ (unsigned long)chirp->code_ra);
+ tree_parse(node, "./psim,description \"map in chrp openboot callback code");
+ tree_parse(node, "./claim 1");
+ tree_parse(node, "./virtual-address 0x%lx",
+ (unsigned long)chirp->code_va);
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_ra);
+ tree_parse(node, "./nr-bytes 0x%lx",
+ (unsigned long)chirp->sizeof_code);
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
+ /* map in the program to run */
+
+ if (chirp->real_mode) {
+ node = tree_parse(node, "/openprom/init/load-binary");
+ tree_parse(node, "./psim,description \"load the binary");
+ tree_parse(node, "./file-name %s", bfd_get_filename(image));
+ tree_parse(node, "./claim 1");
+ }
+ else {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+ (unsigned long)chirp->load_base);
+ tree_parse(node, "./psim,description \"load & map the binary");
+ tree_parse(node, "./claim 1");
+ tree_parse(node, "./file-name \"%s", bfd_get_filename(image));
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
+ /* map in the interrupt vectors */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x0");
+ tree_parse(node, "./psim,description \"map in interrupt vectors");
+ tree_parse(node, "./virtual-address 0x0");
+ tree_parse(node, "./real-address 0x0");
+ tree_parse(node, "./nr-bytes 0x3000");
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
+ return chirp;