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

📄 simmisc.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
  }  if ( BE2HO_8(strSecHdr->sh_size) >= sizeof(strs)) {     Sim_Warning("String table too large if Elf64LoadHeaders\n");     retval = ENOEXEC;     goto error;  }  retval = read(*fd,(char*)strs, BE2HO_8(strSecHdr->sh_size));  if (retval !=  BE2HO_8(strSecHdr->sh_size)){     if (retval < 0) {         retval = errno;        Sim_Warning("Could not reads strings in Elf64LoadHeaders\n");     } else {        retval = ENOEXEC;        Sim_Warning("Read too few strings in Elf64LoadHeaders\n");     }     goto error;  }         for (i=0; i<BE2HO_2(ehdr->e_shnum); i++) {    secName = strs + BE2HO_4(shdr[i].sh_name);    memcpy(secHeaders[i].s_name,secName,8);#if defined(TORNADO)     secHeaders[i].s_vaddr = BE2HO_8(shdr[i].sh_addr);#else    if (IS_XKSEG(BE2HO_8(shdr[i].sh_addr))) {       /* IRIX 6.4 is linked to mapped XKSEG but the kernel seems to         * assume the prom just reads the kernel into low 16MB. */       secHeaders[i].s_vaddr =  XKPHYS_TO_CKSEG0(            (BE2HO_8(shdr[i].sh_addr)-XKSEG_START_ADDR) % (16*1024*1024));    } else if (IS_XKPHYS(BE2HO_8(shdr[i].sh_addr))) {       secHeaders[i].s_vaddr = XKPHYS_TO_CKSEG0(BE2HO_8(shdr[i].sh_addr));    } else if (BE2HO_8(shdr[i].sh_addr) == 0) {       /* IRIX6.4 has some sections that are not used in loading with addr == 0,        and they need to be given a valid s_vaddr for later on */       secHeaders[i].s_vaddr = XKPHYS_TO_CKSEG0(BE2HO_8(shdr[i].sh_addr));    } else {       /* Some of the entry addresses, e.g., that of the boot prom, are          not in xkphys. */       secHeaders[i].s_vaddr = BE2HO_8(shdr[i].sh_addr);    }#endif    secHeaders[i].s_size = BE2HO_8(shdr[i].sh_size);    secHeaders[i].s_scnptr = BE2HO_8(shdr[i].sh_offset);  }    return 0; error:  (void) close(*fd);  return retval;}/***************************************************************** * * Support for loading and starting a kernel image. * *****************************************************************/static intLoadCoffHeaders(char *pathname, 		FILHDR *fileHeader, 		AOUTHDR *aoutHeader, 		SCNHDR secHeaders[MAX_SCNS], 		int *fd, VA *entry){  int retval;  if (!IS_MIPSEBMAGIC(BE2HO_2(fileHeader->f_magic))) {    Sim_Warning("Bad file header in LoadCoffHeaders\n");    retval = ENOEXEC;    goto error;  }    lseek(*fd, sizeof(FILHDR), SEEK_SET);  retval = read(*fd,(char *)aoutHeader, sizeof(AOUTHDR));  if (retval < 0) {    retval = errno;    Sim_Warning("Bad header read in LoadCoffHeaders\n");    goto error;  }    if (BE2HO_2(aoutHeader->magic) != OMAGIC) {    Sim_Warning("Bad header magic number in LoadCoffHeaders\n");    retval = ENOEXEC;    goto error;  }    if (BE2HO_2(fileHeader->f_nscns) >= MAX_SCNS) {    Sim_Warning("Not enough section headers in LoadCoffHeaders\n");    retval = ENOEXEC;    goto error;  }    retval = read(*fd,(char *)secHeaders, sizeof(SCNHDR) *                 BE2HO_2(fileHeader->f_nscns));  if (retval < 0) {    retval = errno;    Sim_Warning("Could not read section headers in LoadCoffHeaders\n");    goto error;  }  if (retval != sizeof(SCNHDR) * BE2HO_2(fileHeader->f_nscns)) {    Sim_Warning("Read too few section headers in LoadCoffHeaders\n");    retval = ENOEXEC;    goto error;  }  *entry = (VA)_SEXT(BE2HO_4(aoutHeader->entry));  return 0;error:  (void) close(*fd);  return retval;}/* * This function allows loading a boot image directly from the disk of * the host system. * Return value is 0 if success, errno if failure. */#define XFER_BUF_SIZE 4096static voidwrite_consistency(int machine, VA startvaddr, int nbytes){  if (CPUVec.CycleCount && (CPUVec.CycleCount(0) > 0)) {    /* system has already started running.  Need to ensure these     * writes are consistent w.r.t. the simulated caches (eg. mipsy     * with data handling) and w.r.t. the cached state in simos (eg.     * embra TC). Can only do page at a time because that is the limit     * for the putmemory functions.     */    while (nbytes > XFER_BUF_SIZE) {      Result res = CPUVec.PutMemory(0, startvaddr, XFER_BUF_SIZE, 				    K0_TO_MEMADDR(machine, startvaddr));      ASSERT(res == SUCCESS);      nbytes     -= XFER_BUF_SIZE;      startvaddr += XFER_BUF_SIZE;    }    if (nbytes > 0) {      Result res = CPUVec.PutMemory(0, startvaddr, nbytes, 				    K0_TO_MEMADDR(machine, startvaddr));      ASSERT(res == SUCCESS);    }  }}typedef enum {  S_TEXT = 0,  S_DATA,       S_RODATA,  S_BSS,  S_GOT,  S_SZ} SegIx;typedef struct SegInfo {  VA  segStart;  int segSize;} SegInfo;#define IN_SEG(_x, _s) (si[_s].segStart <= (_x) &&                 \			(_x) < (si[_s].segStart + si[_s].segSize))static intLoadImage(char* pathname,   /* boot image filename */          int   machine,    /* machine */	  VA    img_addr,   /* image start address */	  VA    ld_addr,    /* load start addres (if diff than above, reloc) */	  int   nbytes,     /* image length (max.) */	  bool  reloc_data, /* relocate data segments? */	  bool* elfFormat,  /* out: ELF file? */	  VA*   entry       /* out: entry point */	  ){  int       fd, retval, i;  HeaderBuf header;  FILHDR    fileHeader;  AOUTHDR   aoutHeader;  SCNHDR    secHeaders[MAX_SCNS];  FILHDR*   hdrPtr;  SegInfo   si[S_SZ]; /* info on segments */  for (i = 0; i < S_SZ; i++) si[i].segSize = 0;  retval = LoadHeaders(pathname, &header, &fileHeader, elfFormat, 		       &aoutHeader, secHeaders, &fd, entry);  if (retval) return retval;  if (!*elfFormat && img_addr != ld_addr) {    CPUError("LoadImage: cannot relocate COFF\n");    retval = EFAULT;    goto error;  }  /* relocate entry point, if necessary */  *entry += (ld_addr - img_addr);  hdrPtr = (*elfFormat) ? &fileHeader : &(header.hb.coffHeader);  ASSERT( BE2HO_2(hdrPtr->f_nscns) < MAX_SCNS);  for (i = 0; i < BE2HO_2(hdrPtr->f_nscns); i++ ) {    VA  sec_addr_k0  = (VA)_SEXT(BE2HO_4(secHeaders[i].s_vaddr));    VA  read_addr_k0 = ld_addr + (sec_addr_k0 - img_addr);    int size         = BE2HO_4(secHeaders[i].s_size);    MA  read_addr_ma = K0_TO_MEMADDR(machine, read_addr_k0);        if (!strcmp(secHeaders[i].s_name, ".text")) {      si[S_TEXT].segStart = sec_addr_k0;   si[S_TEXT].segSize = size;    } else if (!strcmp(secHeaders[i].s_name, ".data")) {      si[S_DATA].segStart = sec_addr_k0;   si[S_DATA].segSize = size;    } else if (!strcmp(secHeaders[i].s_name, ".rodata")) {      si[S_RODATA].segStart = sec_addr_k0; si[S_RODATA].segSize = size;    } else if (!strcmp(secHeaders[i].s_name, ".bss")) {      si[S_BSS].segStart = sec_addr_k0;    si[S_BSS].segSize = size;    } else if (!strcmp(secHeaders[i].s_name, ".got")) {      si[S_GOT].segStart = sec_addr_k0;    si[S_GOT].segSize = size;    }    /* Buggy code by the stanford guys-- what we want is to load     * the whole executable into memory regardless of section names;     * Topsy, for one generates kernel images with wierd segments in them.      *					-- Patryk Zadarnowski *//*****************************************************************************    if ((strcmp(secHeaders[i].s_name, ".text")  == 0)  ||	(strcmp(secHeaders[i].s_name, ".data")  == 0)  ||	(strcmp(secHeaders[i].s_name, ".sdata") == 0)  ||        (strcmp(secHeaders[i].s_name, ".rodata") == 0) ||        (strcmp(secHeaders[i].s_name, ".srdata") == 0) ||        (strcmp(secHeaders[i].s_name, ".lit8") == 0)   ||	(strcmp(secHeaders[i].s_name, ".rdata") == 0)  ||        (strcmp(secHeaders[i].s_name, ".got") == 0) ) {*****************************************************************************/    if (strcmp(secHeaders[i].s_name, ".bss") &&	strcmp(secHeaders[i].s_name, ".sbss"))    {            if (sec_addr_k0 < img_addr || (sec_addr_k0+size) >= img_addr+nbytes) {	CPUError("LoadImage: section %s (va %llx nbytes %x)\r\n"		 "           outside limit (va %x nbytes %x)\n",		 secHeaders[i].s_name, (uint64)secHeaders[i].s_vaddr,		 size, img_addr, nbytes);	retval = EFAULT;	goto error;      }            if (lseek(fd, BE2HO_4(secHeaders[i].s_scnptr), SEEK_SET) !=	  BE2HO_4(secHeaders[i].s_scnptr)) {	retval = errno;	CPUError("Bad section seek in LoadImage\n");	goto error;      }            if (strcmp(secHeaders[i].s_name, ".text") != 0 &&	  img_addr != ld_addr && !reloc_data)	/* don't even load data in the case of replicated text	 * segments sharing the same data.	 */	continue;            if (read(fd, read_addr_ma, size) != size) {	retval = errno;	CPUError("Bad section read in LoadImage - "		 "size = %d, hold = %#x errno %d\n",		 size, K0_TO_MEMADDR(machine, sec_addr_k0), errno);	CPUError("s_vaddr = 0x%08x\n", sec_addr_k0);	goto error;      }      write_consistency(machine, sec_addr_k0, size);    } else if ((strcmp(secHeaders[i].s_name, ".bss") == 0) ||	       (strcmp(secHeaders[i].s_name, ".sbss") == 0)) {      if (sec_addr_k0 < img_addr || (sec_addr_k0+size) >= img_addr+nbytes) {	CPUError("LoadImage: section %s (va %llx nbytes %x)\r\n"		 "           outside limit (va %x nbytes %x)\n",		 secHeaders[i].s_name, (uint64)secHeaders[i].s_vaddr,		 size, img_addr, nbytes);	retval = EFAULT;	goto error;      }            if (img_addr != ld_addr && !reloc_data)	/* don't even load data in the case of replicated text	 * segments sharing the same data.	 */	continue;      memset(read_addr_ma, 0, size);      write_consistency(machine, sec_addr_k0, size);    }  }  if (img_addr != ld_addr) {    VA  got_start_k0 = si[S_GOT].segStart;    VA* got          = (VA*)K0_TO_MEMADDR(machine, got_start_k0);    int got_size     = si[S_GOT].segSize;    /* must relocate -- can do this only for PIC */    if (!got_size) {      CPUError("LoadImage: must relocate but this is not PIC (no GOT).\n");      retval = EFAULT;      goto error;    }    /* go over GOT and perform relocation */    for (i = 0; i < got_size/sizeof(char*); i++) {      if (IN_SEG(got[i], S_TEXT)) {	got[i] += ld_addr - img_addr;	continue;      }      if (!reloc_data)	continue;      if (IN_SEG(got[i], S_DATA) ||	  IN_SEG(got[i], S_RODATA) ||	  IN_SEG(got[i], S_BSS)) {	got[i] += ld_addr - img_addr;	continue;      }      CPUError("LoadImage: bad address in GOT 0x%08x.\n", got[i]);      retval = EFAULT;      goto error;    }    /* make sure GOT is consistent in the caches */    write_consistency(machine, got_start_k0, got_size);  }  retval = 0;  goto done;  error:done:  (void) close(fd);  return retval;}/* * This function is very similar to LoadImage, excet for range checking and placement */static intLoadFPROMImage(char* pathname, VA promAddr, char * promSimAddr,               VA ramAddr, char * ramSimAddr){  int fd, retval, i;  HeaderBuf header;  FILHDR  fileHeader;  AOUTHDR aoutHeader;  SCNHDR  secHeaders[MAX_SCNS];  bool    elfFormat;  FILHDR *hdrPtr;  VA      entry;    retval = LoadHeaders(pathname, &header, &fileHeader, &elfFormat, 		       &aoutHeader, secHeaders, &fd,&entry);  if (retval != 0) {     return retval;  }  if (elfFormat) {    hdrPtr = &fileHeader;  } else {    hdrPtr = &(header.hb.coffHeader);  }    for (i = 0; i < hdrPtr->f_nscns; i++ ) {          if ((strcmp(secHeaders[i].s_name, ".text") == 0) ||         (strcmp(secHeaders[i].s_name, ".data") == 0) ||	 (strcmp(secHeaders[i].s_name, ".sdata") == 0)||         (strcmp(secHeaders[i].s_name, ".rdata") == 0)||	 (strcmp(secHeaders[i].s_name, ".bss") == 0)  ||	 (strcmp(secHeaders[i].s_name, ".sbss") == 0)) {        VA    startaddr;        char *destAddr;        int   nbytes;	VA    s_vaddr = (VA)secHeaders[i].s_vaddr;	int   s_size  = (int)secHeaders[i].s_size;        if (strcmp(secHeaders[i].s_name, ".text") == 0) {           startaddr = promAddr;           nbytes    = FPROM_SIZE;           destAddr  = promSimAddr;        } else {           /* data or bss */           startaddr = ramAddr;           nbytes    = FRAM_SIZE;           destAddr  = ramSimAddr;        }                if (s_vaddr < startaddr || (s_vaddr+s_size) >= startaddr + nbytes) {           CPUError("LoadFPROMImage: section %s (va %x nbytes %x)\r\n"                       "                outside limit (va %x nbytes %x)\n",                       secHeaders[i].s_name, s_vaddr, s_size,                       startaddr, nbytes);           retval = EFAULT;           goto error;        }	if (!secHeaders[i].s_scnptr)	  /* empty - skip */	  continue;        if (lseek(fd, secHeaders[i].s_scnptr, SEEK_SET) !=	      secHeaders[i].s_scnptr) {           retval = errno;           Sim_Warning("Bad section seek in LoadFPROMImage\n");           goto error;        }        if (read(fd, destAddr + (s_vaddr - startaddr), s_size) != s_size) {           retval = errno;           Sim_Warning("Bad section read in LoadFPROMImage\n");           Sim_Warning("s_vaddr = 0x%08x\n", s_vaddr);           goto error;        }     } else if (strcmp(secHeaders[i].s_name, ".comment") == 0) {        /* ignore */     } else {        /* Elf has a lot more section types that are not listed here. */        if (!elfFormat) {           CPUError("Bad section type %s in FPROM.\n", secHeaders[i].s_name);        }     }  }    retval = 0;  error:  (void) close(fd);  return retval;}/* * Copy bootline arguments (for master CPU) into kernel memory so that * kernel will be able to read them. */static voidstore_mem_word(int cpu, VA addr, PromWord val){  PromWord valBE;  if (sizeof(PromWord) == 4) {     valBE = HO2BE_4(val);  } else {     valBE = HO2BE_8(val);  }     ASSERT(IS_KSEG0(addr));  if (sim_misc.myCPUType == MIPSY) {     MemRefDebugWriteData(cpu,addr,K0_TO_PHYS(addr),(char*)&valBE,sizeof(PromWord));  } else {    *((PromWord*)K0_TO_MEMADDR(M_FROM_CPU(cpu), addr)) = valBE;  }}static voidstore_mem_byte(int cpu, VA addr, char c){  ASSERT(IS_KSEG0(addr));  if (sim_misc.myCPUType == MIPSY) {     MemRefDebugWriteData(cpu,addr,K0_TO_PHYS(addr),(char*)&c,sizeof(char));  } else {     *((char*)K0_TO_MEMADDR(M_FROM_CPU(cpu), addr)) = c;  }}static voidcopy_bootline_args(int machine, int argc, char** argv,		   VA* argcVA, VA* argvVA){    int cpu  = FIRST_CPU(machine);    VA argz  = (SIMCP0_KSEG0_ADDR + ARGZONE_OFFS);    VA strp  = argz + (argc + 2)*sizeof(VA);    VA argvp = argz + sizeof(VA);    int i, j;        *argcVA = argz;    *argvVA = argvp;    /* first word: argc */    store_mem_word(cpu, argz, (PromWord)argc);        for (i = 0; i < argc; i++) {        /* store pointer in argv zone */        store_mem_word(cpu, argvp + (sizeof(PromWord)*i), (PromWord)strp);              /* copy argument string */        for (j = 0; argv[i][j]; j++) {            store_mem_byte(cpu, strp, argv[i][j]);             strp++;        }        store_mem_byte(cpu, (VA)strp, 0);         strp++;    }    /* store final 0 in argv */    store_mem_word(cpu, argvp+sizeof(PromWord)*i, 0); }/* * Enter reset vector in boot prom. */

⌨️ 快捷键说明

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