⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emul_chirp.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    /* check the size */    if (head.descsz == sizeof(note->desc) - sizeof(signed32)) {      sim_io_printf_filtered("chirp: note descriptor missing load-base\n");    }    else if (head.descsz != sizeof(note->desc)) {      sim_io_printf_filtered("chirp: note descriptor of wrong size\n");      note->found = note_found;      return;    }    note->found = note_correct;    /* get the contents */    if (!bfd_get_section_contents(image, sect,				  &note->desc, /* page align start */				  ((sizeof(head) + head.namesz) + 3) & ~3,				  head.descsz)) {      error("chirp: note descriptor unreadable\n");    }    note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);    note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);    note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);    note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);    note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);    if (head.descsz == sizeof(note->desc))      note->desc.load_base = bfd_get_32(image, (void*)&note->desc.load_base);    else      note->desc.load_base = (signed32)-1;  }}static os_emul_data *emul_chirp_create(device *root,		  bfd *image,		  const char *name){  os_emul_data *chirp;  device *node;  chirp_note note;  int i;  /* Sanity check that this really is the chosen emulation */  if (name == NULL && image == NULL)    return NULL;  if (name != NULL      && strcmp(name, "ob") != 0      && strcmp(name, "ieee1274") != 0      && strcmp(name, "chrp") != 0      && strcmp(name, "chirp") != 0      && strcmp(name, "openboot") != 0)    return NULL;  /* look for an elf note section, enter its values into the device tree */  memset(&note, 0, sizeof(note));  if (image != NULL)    bfd_map_over_sections(image, map_over_chirp_note, &note);  if (name == NULL && image != NULL && note.found == note_missing)    return NULL;  /* Assume that it is a chirp emulation */  chirp = ZALLOC(os_emul_data);  chirp->root = root;  chirp->services = services;  /* the root node */  tree_parse(root, "/name \"gpl,clayton");  /* default options */  emul_add_tree_options(root, image, "chirp", "oea",			0 /*oea-interrupt-prefix*/);  /* hardware */  emul_add_tree_hardware(root);  /* basic information */  chirp->memory_size    = tree_find_integer_property(root, "/openprom/options/oea-memory-size");  chirp->little_endian    = tree_find_boolean_property(root, "/options/little-endian?");  chirp->floating_point_available    = tree_find_boolean_property(root, "/openprom/options/floating-point?");  chirp->interrupt_prefix =    tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");  /* Perform an interum layout of the openboot firmware in memory */  /* a page for firmware calls */  chirp->sizeof_code = 4096;  chirp->code_offset = 0x4000; /* possible space for interrupt table */  /* the stack */  chirp->sizeof_stack = 32 * 1024;  chirp->stack_offset = chirp->code_offset + chirp->sizeof_code;  /* the hash table */  if (!note.desc.real_mode) {    chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000					 ? 1024 /* min allowed */					 : (chirp->memory_size / 4096 / 2));    chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;  }  chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack;  /* the actual amount of space needed */  chirp->real_size = chirp->htab_offset + chirp->sizeof_htab;  /* now go through and see if it fits in what is available */  /* resolve real-mode? */  if (note.found == note_correct)    chirp->real_mode = note.desc.real_mode;  else if (tree_find_property(root, "/options/real-mode?") != NULL)    chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?");  else    chirp->real_mode = 0;  if (tree_find_property(root, "/options/real-mode?") != NULL) {    if (!chirp->real_mode	!= !tree_find_boolean_property(root, "/options/real-mode?"))      error("chirp: /options/real-mode? conflicts with note section\n");  }  else    tree_parse(root, "/options/real-mode? %s",	       chirp->real_mode ? "true" : "false");  /* resolve real-base */  if (note.found == note_correct      && note.desc.real_base != (signed32)-1)    chirp->real_base = note.desc.real_base;  else if (tree_find_property(root, "/options/real-base") != NULL)    chirp->real_base = tree_find_integer_property(root, "/options/real-base");  else    chirp->real_base = chirp->memory_size - chirp->real_size;  if (tree_find_property(root, "/options/real-base") != NULL) {    if (chirp->real_base != tree_find_integer_property(root, "/options/real-base"))      error("chirp: /options/real-base conflicts with note section\n");  }  else    tree_parse(root, "/options/real-base 0x%lx",	       (unsigned long)chirp->real_base);  /* resolve real-size */  if (note.found == note_correct      && note.desc.real_size != (signed32)-1      && note.desc.real_size != 0      && chirp->real_size > note.desc.real_size)    error("chirp: insufficient physical memory for firmware\n");  if (tree_find_property(root, "/options/real-size") != NULL) {    if (chirp->real_size > tree_find_integer_property(root, "/options/real-size"))      error("chirp: /options/real-size conflicts with note section\n");  }  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;}static voidemul_chirp_init(os_emul_data *emul_data,		int nr_cpus){  emul_data->state = serving;}static intemul_chirp_instruction_call(cpu *processor,			    unsigned_word cia,			    unsigned_word ra,			    os_emul_data *emul_data){  unsigned_word service_name_addr;  unsigned_word result;  char service_buf[32];  char *service_name;  chirp_services *service;  switch (emul_data->state) {  case serving:    /* we are waiting on an OpenBoot request from the client program       via the client interface */    if (cia != emul_data->code_client_va)      return 0;    emul_data->return_address = LR;    emul_data->arguments = cpu_registers(processor)->gpr[3];    /* try to determine what to do */    service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3],				       processor, cia);    service_name = emul_read_string(service_buf, service_name_addr,				    sizeof(service_buf), processor, cia);    emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell),				       processor, cia);    emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell),					  processor, cia);    /* verify what was passed */    if (service_name_addr == 0	|| service_name == NULL) {      error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",	    (unsigned long)emul_data->return_address,	    (unsigned long)emul_data->arguments);    }    if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */      error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",	    (unsigned long)emul_data->return_address,	    (unsigned long)emul_data->arguments,	    emul_data->n_returns);    }    if (emul_data->n_returns > 6) {      error("OpenFirmware service %s called from 0x%lx with args 0x%lx,  with too many returns (%d)\n",	    (unsigned long)emul_data->return_address,	    (unsigned long)emul_data->arguments,	    emul_data->n_args);    }    /* look it up */    TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",			  service_name,			  (unsigned long)emul_data->return_address,			  (unsigned long)emul_data->arguments));    service = services;    while (service->name != NULL && strcmp(service->name, service_name) != 0)      service++;    /* found or not? */    if (service->name == NULL) {      error("OpenBoot service `%s' not found\n", service_name);      TRACE(trace_os_emul, ("%s not found\n", service_name));      cpu_registers(processor)->gpr[3] = -1;    }    else {      emul_data->service = service;      /* call upon it */      result = service->handler(emul_data, processor, cia);      if (result != 0)	TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result));      cpu_registers(processor)->gpr[3] = result;    }    break;  default:    error("emul_chirp_instruction_call() unknown internal state\n");    result = -1;    break;  }  /* return to caller - instruction following this is a function return */  return 1;}const os_emul emul_chirp = {  "chirp",  emul_chirp_create,  emul_chirp_init,  NULL, /*system_call*/  emul_chirp_instruction_call,  0 /*data*/};#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -