/* Nios-sim - one simple NIOSII simulator only for personal interest and fun. Copyright (C) 2010 chysun2000@gmail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include "public.h" #include "nor_flash.h" typedef enum { S_INVALID = 0x00, S0 = 0x01, S1 = 0x02, S2 = 0x03, S3 = 0x04, S4 = 0x05, S5 = 0x06, S6 = 0x07, S7 = 0x08, S8 = 0x09, S9 = 0x0A } SREC_TYPE; static struct image_info image_info; static int32_t is_line_end(char data) { if (data == '\n'){ return 0; } else{ return -1; } } static void get_line(FILE * fp, char * buf, int32_t buf_len, int32_t * line_len) { char data = '\0'; int32_t index = 0; memset(buf, 0x00, buf_len); while(1){ if(feof(fp) != 0 || ferror(fp) != 0){ return ; } data = '\0'; if (fread(&data, 1, 1, fp) == 1){ if (is_line_end(data) != 0){ buf[index++] = data; *line_len = index; } else { return ; } } else { return ; } } } static SREC_TYPE get_srec_type(char * buf) { if (buf[1] >= 0x30 && buf[1] <= 0x39){ return S0 + buf[1] - 0x30; } else{ return S_INVALID; } } static uint32_t __factors [] = { 1, 16, 256, 16 * 16 * 16, 16 * 16 * 16 * 16, 16 * 16 * 16 * 16 * 16, 16 * 16 * 16 * 16 * 16 * 16, 16 * 16 * 16 * 16 * 16 * 16 * 16 }; static uint32_t single_ascii_to_hex(char data) { if (data >= 0x30 && data <= 0x39) return data - 0x30; if (data >= 0x41 && data <= 0x46) return data - 0x41 + 10; if (data >= 0x61 && data <= 0x66) return data - 0x61 + 10; return 0; } uint32_t ascii_to_hex(char * buf, uint32_t buf_len) { uint32_t ret = 0x0000; int32_t i = 0; for (i=0;i> 24); ret = ret | ((data & 0x00FF0000) >> 8); ret = ret | ((data & 0x0000FF00) << 8); ret = ret | ((data & 0x000000FF) << 24); return ret; } #define S0_DATA_OFFSET (8) #define S0_ADDR_CRC_CNT (3) static uint32_t handle_S0(char * buf, uint32_t data_count, uint32_t * mem_base) { int32_t i = 0; char * data_buf = buf; data_buf = data_buf + S0_DATA_OFFSET; for (i=0;i can not open image at %s\n", image_path_name); } } void load_image(void) { switch(image_info.image_format){ case SREC_FMT: load_srec(image_info.path_name, image_info.mem_base); break; default: break; } } void alloc_image_mem(void) { char * address = NULL; struct image_info * info = &image_info; uint32_t temp = 0; address = (char *)malloc(info->mem_size); temp = info->mem_size % 4; if (temp != 0){ address = address + temp; } info->mem_base = (uint32_t *)address; } void set_image_pathname(char * pathname) { image_info.path_name = pathname; } void set_image_format(IMG_FORMAT format) { image_info.image_format = format; } void set_image_memsize(char * size) { int32_t str_len = strlen(size); char * temp = NULL; if (size[str_len - 1] == 'M' || size[str_len - 1] == 'm'){ temp = malloc(str_len); memset(temp, 0x00, str_len); memcpy(temp, size, str_len); temp[str_len - 1] = '\0'; image_info.mem_size = atoi(temp) * 1024 * 1024; free(temp); } } void set_image_entry_addr(uint32_t addr) { image_info.entry_addr = addr; } void set_image_base_addr(char * addr) { sscanf(addr, "0x%X\n", &image_info.base_addr); } static char cmd_line[256] = {0}; static uint32_t initrd_start = 0; static uint32_t initrd_size = 0; static char fs_image[256] = {0}; void print_image_info(void) { printf("--------------------------------------------------\n"); printf(" NIOS Simulator (Built at %s-%s)\n",__DATE__,__TIME__); printf("--------------------------------------------------\n"); printf("Image File:%s\n",image_info.path_name); if (image_info.image_format == SREC_FMT){ printf("Format:SREC\n"); } printf("Mem size:0x%08X, loading at %p\n", image_info.mem_size, image_info.mem_base); printf("Base address:0x%08X, Entry address:0x%08X\n",image_info.base_addr, image_info.entry_addr); printf("Set command line:%s\n", cmd_line); printf("Initrd: 0x%08x size:0x%08x\n",initrd_start, initrd_size); printf("rootfs: %s \n",fs_image); printf("--------------------------------------------------\n"); } struct image_info * get_image_info(void) { return &image_info; } static struct symbol_obj * sym_hash[256] = {NULL}; static struct symbol_obj * get_head_list(uint32_t addr) { return sym_hash[addr % 256]; } static void insert_symbol_obj(struct symbol_obj * list, struct symbol_obj * obj) { if (list == NULL){ sym_hash[obj->addr % 256] = obj; } else{ while(list != NULL){ if (list->next != NULL){ list = list->next; } else{ break; } } list->next = obj; } } static struct symbol_obj * alloc_symbol_obj(char * addr, char * name) { struct symbol_obj * obj = NULL; uint32_t size = 0; obj = (struct symbol_obj *)malloc(sizeof(struct symbol_obj)); memset(obj, 0x00, sizeof(struct symbol_obj)); if (obj != NULL){ obj->addr = ascii_to_hex(addr, 8); obj->next = NULL; size = strlen(name) + 1; obj->sym_name = (char *)malloc(size); if (obj->sym_name != NULL){ memset(obj->sym_name, 0x00, size); strncpy(obj->sym_name, name, size - 1); } else{ printf("[ERROR] %s --> can not allocate symname %s \n",__func__, name); } } return obj; } static void handle_symbol_line(char * line) { char addr[10] = {0}; char sym_name[64] = {0}; char type[2] = {0}; struct symbol_obj * obj = NULL; struct symbol_obj * list = NULL; memset(sym_name, 0x00, 64); sscanf(line, "%s %s %s\n", addr, type, sym_name); obj = alloc_symbol_obj(addr, sym_name); if (obj != NULL){ list = get_head_list(obj->addr); insert_symbol_obj(list, obj); } } void load_symbol_file(char * symbol_file) { char line[256] = {0}; int32_t line_len = 0; FILE * fp = NULL; memset(sym_hash, 0x00, sizeof(sym_hash)); fp = fopen(symbol_file, "r"); if (fp != NULL){ while(1){ memset(line, 0x00, 256); line_len = 0; get_line(fp, line, 256, &line_len); if (line_len == 0){ break; } else{ line[line_len] = '\0'; handle_symbol_line(line); } } fclose(fp); } } static struct symbol_obj * find_symbol_obj(struct symbol_obj * list, uint32_t addr) { struct symbol_obj * ret = NULL; ret = list; while(ret != NULL){ if (ret->addr == addr){ break; } else{ ret = ret->next; } } return ret; } struct symbol_obj * get_symbol(uint32_t addr) { struct symbol_obj * ret = NULL; struct symbol_obj * lst = NULL; lst = get_head_list(addr); if (lst != NULL){ ret = find_symbol_obj(lst, addr); } return ret; } void set_cmdline(char * optarg) { strcpy(cmd_line,optarg); } void init_cmdline(struct NIOS_CPU * cpu) { char * addr = (char *)image_info.mem_base; /* R7 is stored the start address of command line */ memcpy((char *)(addr + 0x700000), cmd_line, 255); /* Set magic number. * this is copied from arch/nios2/kernel/setup.c */ if (cmd_line[0] != '\0'){ cpu->gp_regs[4] = 0x534f494e; cpu->gp_regs[7] = 0xF00000; } } void set_initrd(char * optarg) { sscanf(optarg,"0x%08x,0x%08x",&initrd_start,&initrd_size); } void init_initrd(struct NIOS_CPU * cpu) { cpu->gp_regs[5] = initrd_start & 0xFFFFFFFC; cpu->gp_regs[6] = (initrd_start + initrd_size) & 0xFFFFFFFC; } void set_fs_image(char * optarg) { sscanf(optarg,"%s",fs_image); } void init_fs_image(struct NIOS_CPU * cpu) { int32_t fd = open(fs_image,O_RDWR); int32_t size = 0; uint8_t buf [256] = {0}; uint8_t * mem_load_addr = NULL; /* set the load memory address */ mem_load_addr = nor_flash_mem_addr(); if (fd){ printf("loading rootfs at %p\n", mem_load_addr); while((size = read(fd,buf, 256)) > 0){ memcpy(mem_load_addr, buf, size); mem_load_addr += size; } close(fd); } else { printf("Can not load rootfs image at %s\n",fs_image); } } /*----------------------------------------------------------------------------*/