📄 linux_init.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//***************************************************************** * Attempt to set up the linux tags so that the kernel can grab * configuration information. *****************************************************************/#include <stdio.h>#include <stdlib.h>#include <sys/file.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <string.h>#include "linux_init.h"#include "sim.h"#include "addr_layout.h"#include "simmisc.h"#include "machine_params.h"#include "sim_error.h"#define TAGVALPTR(t) ((void*)(((void*)(t)) - ((t)->size)))#define NEXTTAGPTR(t) ((void*)(TAGVALPTR(t) - (sizeof(tag))))TagList tagPairs;void LongTagSet(long_tag *initTag, enum bi_tag type, unsigned long size, long val);void IntTagSet(int_tag *initTag, enum bi_tag type, unsigned long size,int val);static struct nlist *get_nlist(char *symbol);static char *ld_isymbol(char *symbol);/***************************************************************** * Initialize all the tags to their default values. * * Note that we have not initialzied the drive_info or the * mount_root_rdonly field, as they should not concern us. *****************************************************************/voidTagInit(int machine, TagList* tagPairs) { ASSERT( MEM_SIZE(machine) > 1024 * 1024); IntTagSet(&(tagPairs->machtype),tag_machtype,sizeof(int),MACH_SIMOS_PORT0); IntTagSet(&(tagPairs->cputype),tag_cputype,sizeof(int),CPU_R4400SC); LongTagSet(&(tagPairs->memlower),tag_memlower,sizeof(long),0); LongTagSet(&(tagPairs->memupper),tag_memupper,sizeof(long),(long)(MEM_SIZE(machine) + K0BASE)); LongTagSet(&(tagPairs->icache_size),tag_icache_size,sizeof(long),(1024*32)); LongTagSet(&(tagPairs->icache_linesize),tag_icache_linesize,sizeof(long),(64)); LongTagSet(&(tagPairs->dcache_size),tag_dcache_size,sizeof(long),(1024*32)); LongTagSet(&(tagPairs->dcache_linesize),tag_dcache_linesize,sizeof(long),(64)); LongTagSet(&(tagPairs->scache_size),tag_scache_size,sizeof(long),(1024*1024)); LongTagSet(&(tagPairs->scache_linesize),tag_scache_linesize,sizeof(long),(128)); IntTagSet(&(tagPairs->tlb_entries),tag_tlb_entries,sizeof(int),64); IntTagSet(&(tagPairs->ramdisk_size),tag_ramdisk_size,sizeof(int),0); IntTagSet(&(tagPairs->ramdisk_base),tag_ramdisk_base,sizeof(int),0); IntTagSet(&(tagPairs->mount_root_rdonly),tag_mount_root_rdonly,sizeof(int),0); IntTagSet(&(tagPairs->vram_base),tag_vram_base,sizeof(int),0); IntTagSet(&(tagPairs->machgroup),tag_machgroup,sizeof(int),MACH_GROUP_SIMOS); tagPairs->command_line.atag.tag = tag_command_line; tagPairs->command_line.atag.size = COMMAND_LINE_SIZE; tagPairs->command_line.data[0] = '\0'; tagPairs->drive_info.atag.tag = tag_drive_info; tagPairs->drive_info.atag.size = sizeof(struct drive_info_struct); tagPairs->dummy.tag = tag_dummy; tagPairs->dummy.size = 0; return;}void IntTagSet(int_tag *initTag, enum bi_tag type, unsigned long size,int val){ initTag->atag.tag = type; initTag->atag.size = size; initTag->data = val;} void LongTagSet(long_tag *initTag, enum bi_tag type, unsigned long size, long val){ initTag->atag.tag = type; initTag->atag.size = size; initTag->data = val;}/***************************************************************** * I can't get this kernel into COFF format, so we need * our own loader for its a.out-ish format. *****************************************************************/static struct nlist *symbols;static char *strings;static long strsize, numsymbols;intLinuxLoadImage(char *pathname, VA startaddr, int nbytes, VA* entry, int filter){ int sfd, fd, retval; struct exec kexec; struct nlist *n1; off_t filesize; Sim_Warning("inside LinuxLoadImage\n"); /* Shouldn't reach this --ejs */ return (ENOEXEC);#if 0 *** We no longer use this function to load the linux kernel --ejs /* TagInit(); debugging --ejs*/ if ((fd = open (pathname, O_RDONLY)) < 0) { retval = errno; goto error; } if (read (fd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) { Sim_Warning("LinuxLoadImage: Bad header read\n"); retval = ENOEXEC; goto error; } if(N_MAGIC(kexec) != OMAGIC && N_MAGIC(kexec) != NMAGIC && N_MAGIC(kexec) != ZMAGIC && N_MAGIC(kexec) != QMAGIC) { Sim_Warning("LinuxLoadImage: Bad header magic number\n"); retval = ENOEXEC;/* goto error;*/ } if (N_MACHTYPE(kexec) != M_MIPS1 && N_MACHTYPE(kexec) != M_MIPS2) { Sim_Warning("LinuxLoadImage: Bad machine type\n"); retval = ENOEXEC; goto error; } /* * Read file's symbol table * * Open kernel executable and read exec header - we need to * use a second open file since the ARC standard doesn't * support reverse seeking on files which might run us in * trouble later on. */ if ((sfd = open (pathname, O_RDONLY)) == -1) { retval = errno; goto error; } symbols = (struct nlist *)malloc (kexec.a_syms); if (!symbols) { retval = errno; goto error; }/* seeking to symbol table */ lseek (sfd, N_SYMOFF(kexec), SEEK_SET);/* Reading symbol table */ read (sfd, symbols, kexec.a_syms); numsymbols = kexec.a_syms / sizeof (struct nlist); filesize = lseek (sfd, 0, SEEK_END); strsize = filesize - N_STROFF(kexec); strings = (char *)malloc (strsize); if (!strings) { free (symbols); symbols = NULL; goto error; } lseek (sfd, N_STROFF(kexec), SEEK_SET); read (sfd, strings, strsize); /* read text and data segments in at K0BASE. Zero out BSS */ if (lseek (fd, N_TXTOFF(kexec), SEEK_SET) == -1) { Sim_Warning("LinuxLoadImage: Can't seek to text\n"); retval = ENOEXEC; goto error; } Sim_Warning("LinuxLoadImage: Load text to %#x size %#x\n", (char *)K0_TO_MEMADDR(BE2HO_4(startaddr)), BE2HO_4(kexec.a_text)); if ((retval = read(fd, (char *)K0_TO_MEMADDR(BE2HO_4(startaddr)), BE2HO_4(kexec.a_text)) ) != kexec.a_text) { Sim_Warning("LinuxLoadImage: Couldn't read text segment - size %#x of %#x\n", retval, kexec.a_text); retval = ENOEXEC; goto error; } if (lseek(fd, N_DATOFF(kexec), SEEK_SET) == -1) { Sim_Warning("LinuxLoadImage: Can't seek to data\n"); retval = ENOEXEC; goto error; } Sim_Warning("LinuxLoadImage: Load data to %#x size %#x\n", (char *)K0_TO_MEMADDR(BE2HO_4(startaddr+kexec.a_text)), BE2HO_4(kexec.a_data)); if (read (fd, (char *)K0_TO_MEMADDR(BE2HO_4(startaddr + kexec.a_text)), BE2HO_4(kexec.a_data)) != kexec.a_data) { Sim_Warning("LinuxLoadImage: Couldn't read data segment\n"); retval = ENOEXEC; goto error; } memset((char *) K0_TO_MEMADDR(BE2HO_4(startaddr + kexec.a_text + kexec.a_data)), 0, kexec.a_bss); /* set value of a0 to startaddr, which is K0BASE */ Sim_Warning("Read in kexec.a_entry 0x%x\n", kexec.a_entry); if (!(n1 = get_nlist(ld_isymbol("stext")))) { Sim_Warning("LinuxLoadImage: Couldn't read kernel_entry from symbol table\n"); retval = ENOEXEC; goto error; } else { Sim_Warning("The symb tab entry: 0x%x, the header entry 0x%x sizeof header 0x%x\n",n1->n_value,kexec.a_entry, sizeof(kexec)); } retval = 0; /* CHANGE THIS */ *entry = (aout_entryfunc) (n1->n_value );/* *entry = (aout_entryfunc) kexec.a_entry;*/ error: if (strings) { free (strings); } if (symbols) { free (symbols); symbols = NULL; } (void) close(fd); (void) close(sfd); return(retval);#endif }/* * Read a symbol from the kernel executable */static struct nlist *get_nlist(char *symbol){ struct nlist *nl, *p = NULL; for (nl = symbols; nl < symbols + numsymbols; nl++) { /* * We accept only extern visible .text, .data and .bss symbols. */ if (strcmp (symbol, strings + nl->n_un.n_strx) == 0 && ((nl->n_type == N_TEXT | N_EXT) || (nl->n_type == N_DATA | N_EXT) || (nl->n_type == N_BSS | N_EXT))) { p = (struct nlist *)malloc (sizeof (struct nlist) + strlen(strings + nl->n_un.n_strx) + 1); if (!p) break; *p = *nl; p->n_un.n_name = (char *)(p+1); strcpy (p->n_un.n_name, strings + nl->n_un.n_strx); } } return p;}static char *ld_isymbol(char *symbol){ static char isymbol[64]; /* strcpy(isymbol, STR(C_LABEL_PREFIX));*/ strcat(isymbol, symbol); return isymbol;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -