📄 emul_chirp.c
字号:
/* OpenFirmware doesn't define this error */ error("chirp: invalid ihandle passed to read method"); } else { /* do the reads */ int actual = 0; while (actual < args.len) { int remaining = args.len - actual; int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf)); int nr_read = device_instance_read(ihandle, buf, to_read); if (nr_read < 0) { actual = nr_read; /* the error */ break; } else if (nr_read == 0) { break; } emul_write_buffer(buf, args.addr + actual, nr_read, processor, cia); actual += nr_read; } if (actual >= 0) { args.actual = actual; if (actual < sizeof(buf)) buf[actual] = '\0'; else buf[sizeof(buf) - 1] = '\0'; } else { switch (actual) { case sim_io_eof: args.actual = 0; break; case sim_io_not_ready: ASSERT(sim_io_not_ready == -2); args.actual = sim_io_not_ready; break; default: error("Bad error value %ld", (long)actual); break; } } } /* return the result */ TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n", (long)args.actual, ((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "") )); chirp_write_h2t_args(&args, sizeof(args), data, processor, cia); return 0;}static intchirp_emul_write(os_emul_data *data, cpu *processor, unsigned_word cia){ struct write_args { /*in*/ unsigned_cell ihandle; unsigned_cell addr; unsigned_cell len; /*out*/ unsigned_cell actual; } args; char buf[1024]; device_instance *ihandle; int actual; /* get the args */ if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) return -1; actual = args.len; if (actual >= sizeof(buf)) actual = sizeof(buf) - 1; emul_read_buffer(buf, args.addr, actual, processor, cia); buf[actual] = '\0'; ihandle = external_to_device_instance(data->root, args.ihandle); TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n", (unsigned long)args.ihandle, (unsigned long)ihandle, ihandle_name(ihandle), buf, (long)actual)); if (ihandle == NULL) { /* OpenFirmware doesn't define this error */ error("chirp: invalid ihandle passed to write method"); } else { /* write it out */ actual = device_instance_write(ihandle, buf, actual); if (actual < 0) args.actual = 0; else args.actual = actual; } /* return the result */ TRACE(trace_os_emul, ("write - out - actual=%ld\n", (long)args.actual)); chirp_write_h2t_args(&args, sizeof(args), data, processor, cia); return 0;}static intchirp_emul_seek(os_emul_data *data, cpu *processor, unsigned_word cia){ struct seek_args { /*in*/ unsigned_cell ihandle; unsigned_cell pos_hi; unsigned_cell pos_lo; /*out*/ unsigned_cell status; } args; int status; device_instance *ihandle; /* get the args */ if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) return -1; ihandle = external_to_device_instance(data->root, args.ihandle); TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n", (unsigned long)args.ihandle, (unsigned long)ihandle, ihandle_name(ihandle), args.pos_hi, args.pos_lo)); if (ihandle == NULL) { /* OpenFirmware doesn't define this error */ error("chirp: invalid ihandle passed to seek method"); } else { /* seek it out */ status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo); args.status = status; } /* return the result */ TRACE(trace_os_emul, ("seek - out - status=%ld\n", (long)args.status)); chirp_write_h2t_args(&args, sizeof(args), data, processor, cia); return 0;}/* memory */static intchirp_emul_claim(os_emul_data *data, cpu *processor, unsigned_word cia){ /* NOTE: the client interface claim routine is *very* different to the "claim" method described in IEEE-1275 appendix A. The latter uses real addresses while this uses virtual (effective) addresses. */ struct claim_args { /* in */ unsigned_cell virt; unsigned_cell size; unsigned_cell align; /* out */ unsigned_cell baseaddr; } args; /* read the args */ if (chirp_read_t2h_args(&args, sizeof(args), 3 /*n_args*/, 1 /*n_returns*/, data, processor, cia)) return -1; TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n", (unsigned long)args.virt, (long int)args.size, (int)args.align)); /* use the memory device to allocate (real) memory at the requested address */ { device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory"); unsigned_cell mem_in[3]; unsigned_cell mem_out[1]; mem_in[0] = args.align; /*top-of-stack*/ mem_in[1] = args.size; mem_in[2] = args.virt; if (device_instance_call_method(memory, "claim", 3, mem_in, 1, mem_out) < 0) error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d", (unsigned long)args.virt, (long int)args.size, (int)args.align); args.baseaddr = mem_out[0]; } /* if using virtual addresses, create a 1-1 map of this address space */ if (!data->real_mode) { error("chirp: claim method does not support virtual mode"); } /* return the base address */ TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n", (unsigned long)args.baseaddr)); chirp_write_h2t_args(&args, sizeof(args), data, processor, cia); return 0;}static intchirp_emul_release(os_emul_data *data, cpu *processor, unsigned_word cia){ /* NOTE: the client interface release routine is *very* different to the "claim" method described in IEEE-1275 appendix A. The latter uses real addresses while this uses virtual (effective) addresses. */ struct claim_args { /* in */ unsigned_cell virt; unsigned_cell size; /* out */ } args; /* read the args */ if (chirp_read_t2h_args(&args, sizeof(args), 2 /*n_args*/, 0 /*n_returns*/, data, processor, cia)) return -1; TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n", (unsigned long)args.virt, (long int)args.size)); /* use the memory device to release (real) memory at the requested address */ { device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory"); unsigned_cell mem_in[2]; mem_in[0] = args.size; mem_in[1] = args.virt; if (device_instance_call_method(memory, "release", 2, mem_in, 0, NULL) < 0) error("chirp: claim failed to release memory virt=0x%lx size=%ld", (unsigned long)args.virt, (long int)args.size); } /* if using virtual addresses, remove the 1-1 map of this address space */ if (!data->real_mode) { error("chirp: release method does not support virtual mode"); } /* return the base address */ TRACE(trace_os_emul, ("release - out\n")); chirp_write_h2t_args(&args, sizeof(args), data, processor, cia); return 0;}/* Control transfer */static intchirp_emul_boot(os_emul_data *data, cpu *processor, unsigned_word cia){ /* unlike OpenFirmware this one can take an argument */ struct boot_args { /*in*/ unsigned_cell bootspec; /*out*/ } args; char bootspec[1024]; /* read in the arguments */ if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia)) cpu_halt(processor, cia, was_exited, -1); if (args.bootspec != 0) emul_read_string(bootspec, args.bootspec, sizeof(bootspec), processor, cia); else strcpy(bootspec, "(null)"); TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec)); /* just report this and exit */ printf_filtered("chrp: boot %s called, exiting.\n", bootspec); cpu_halt(processor, cia, was_exited, 0); return 0;}static intchirp_emul_enter(os_emul_data *data, cpu *processor, unsigned_word cia){ error("chirp: enter method not implemented\n"); return 0;}static intchirp_emul_exit(os_emul_data *data, cpu *processor, unsigned_word cia){ /* unlike OpenBoot this one can take an argument */ struct exit_args { /*in*/ signed_cell status; /*out*/ } args; if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia)) cpu_halt(processor, cia, was_exited, -1); cpu_halt(processor, cia, was_exited, args.status); return 0;}static intchirp_emul_chain(os_emul_data *data, cpu *processor, unsigned_word cia){ error("chirp: chain method not implemented\n"); return 0;}/* user interface */static intchirp_emul_interpret(os_emul_data *data, cpu *processor, unsigned_word cia){ error("chirp: interpret method not implemented\n"); return 0;}static intchirp_emul_set_callback(os_emul_data *data, cpu *processor, unsigned_word cia){ error("chirp: set_callback method not implemented\n"); return 0;}static intchirp_emul_set_symbol_lookup(os_emul_data *data, cpu *processor, unsigned_word cia){ error("chirp: set_symbol_lookup method not implemented\n"); return 0;}/* Time */static intchirp_emul_milliseconds(os_emul_data *data, cpu *processor, unsigned_word cia){ struct test_args { /*in*/ /*out*/ unsigned_cell ms; } args; unsigned64 time; /* read in the arguments */ if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; /* make up a number */ time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000; args.ms = time; /* write the arguments back out */ TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n", (unsigned long)args.ms)); chirp_write_h2t_args(&args, sizeof(args), data, processor, cia); return 0;}static chirp_services services[] = { /* client interface */ { "test", chirp_emul_test }, /* device tree */ { "peer", chirp_emul_peer }, { "child", chirp_emul_child }, { "parent", chirp_emul_parent }, { "instance-to-package", chirp_emul_instance_to_package }, { "getproplen", chirp_emul_getproplen }, { "getprop", chirp_emul_getprop }, { "nextprop", chirp_emul_nextprop }, /* { "setprop", chirp_emul_setprop }, */ { "canon", chirp_emul_canon }, { "finddevice", chirp_emul_finddevice }, { "instance-to-path", chirp_emul_instance_to_path }, { "package-to-path", chirp_emul_package_to_path }, { "call-method", chirp_emul_call_method }, /* device I/O */ { "open", chirp_emul_open }, { "close", chirp_emul_close }, { "read", chirp_emul_read }, { "write", chirp_emul_write }, { "seek", chirp_emul_seek }, { "write", chirp_emul_write }, /* memory */ { "claim", chirp_emul_claim }, { "release", chirp_emul_release }, /* control transfer */ { "boot", chirp_emul_boot }, { "enter", chirp_emul_enter }, { "exit", chirp_emul_exit }, { "chain", chirp_emul_chain }, /* user interface */ { "interpret", chirp_emul_interpret }, { "set_callback", chirp_emul_set_callback }, { "set_symbol_lookup", chirp_emul_set_symbol_lookup }, /* time */ { "milliseconds", chirp_emul_milliseconds }, { 0, /* sentinal */ },};/* main handlers *//* Any starting address greater than this is assumed to be an Chirp rather than VEA */#ifndef CHIRP_START_ADDRESS#define CHIRP_START_ADDRESS 0x80000000#endif#ifndef CHIRP_LOAD_BASE#define CHIRP_LOAD_BASE -1#endiftypedef struct _chirp_note_desc { signed32 real_mode; signed32 real_base; signed32 real_size; signed32 virt_base; signed32 virt_size; signed32 load_base;} chirp_note_desc;typedef enum { note_missing, note_found, note_correct,} note_found_status;typedef struct _chirp_note { chirp_note_desc desc; note_found_status found;} chirp_note;typedef struct _chirp_note_head { unsigned32 namesz; unsigned32 descsz; unsigned32 type;} chirp_note_head;static voidmap_over_chirp_note(bfd *image, asection *sect, PTR obj){ chirp_note *note = (chirp_note*)obj; if (strcmp(sect->name, ".note") == 0) { chirp_note_head head; char name[16]; /* check the head */ if (!bfd_get_section_contents(image, sect, &head, 0, sizeof(head))) return; head.namesz = bfd_get_32(image, (void*)&head.namesz); head.descsz = bfd_get_32(image, (void*)&head.descsz); head.type = bfd_get_32(image, (void*)&head.type); if (head.type != 0x1275) return; /* check the name field */ if (head.namesz > sizeof(name)) { error("chirp: note name too long (%d > %d)\n", (int)head.namesz, sizeof(name)); } if (!bfd_get_section_contents(image, sect, name, sizeof(head), head.namesz)) { error("chirp: note name unreadable\n"); } if (strcmp(name, "PowerPC") != 0) { printf_filtered("chirp: note name (%s) not `PowerPC'\n", name); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -