📄 simmisc.c
字号:
} 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 + -