📄 dev_c3745.c
字号:
/* * Cisco 3745 simulation platform. * Copyright (c) 2006 Christophe Fillot (cf@utc.fr) * * Generic Cisco 3745 routines and definitions (EEPROM,...). */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <assert.h>#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "pci_io.h"#include "dev_gt.h"#include "cisco_eeprom.h"#include "dev_c3745.h"#include "dev_vtty.h"#include "registry.h"/* ======================================================================== *//* EEPROM definitions *//* ======================================================================== *//* Cisco 3745 motherboard EEPROM */static m_uint16_t eeprom_c3745_motherboard_data[] = { 0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809, 0x6940, 0x02F7, 0xC046, 0x0320, 0x003E, 0x3E03, 0x4241, 0x3085, 0x1C12, 0x4004, 0x80FF, 0xFFFF, 0xFFC4, 0x08FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFF81, 0x0000, 0x0000, 0x0400, 0x0300, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4102, 0x0002, 0x04C2, 0x8B58, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,};struct cisco_eeprom eeprom_c3745_motherboard = { "C3745 Motherboard", eeprom_c3745_motherboard_data, sizeof(eeprom_c3745_motherboard_data)/2,};/* Cisco 3745 I/O board EEPROM */static m_uint16_t eeprom_c3745_ioboard_data[] = { 0x04FF, 0x4002, 0xF841, 0x0200, 0xC046, 0x0320, 0x0038, 0x7E01, 0x4242, 0x3080, 0x0000, 0x0000, 0x0203, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5803, 0x0081, 0x0000, 0x0000, 0x0400, 0xC809, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC2, 0x8B58, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,};struct cisco_eeprom eeprom_c3745_ioboard = { "C3745 I/O board", eeprom_c3745_ioboard_data, sizeof(eeprom_c3745_ioboard_data)/2,};/* Cisco 3745 midplane EEPROM */static m_uint16_t eeprom_c3745_midplane_data[] = { 0x04FF, 0x4003, 0x3E41, 0x0200, 0xC046, 0x0320, 0x0030, 0x0101, 0x4241, 0x3080, 0x0000, 0x0000, 0x0205, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5803, 0x0081, 0x0000, 0x0000, 0x0400, 0xC809, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC3, 0x0600, 0x0DED, 0xCD7D, 0x8043, 0x0050, 0xC28B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x58FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,};struct cisco_eeprom eeprom_c3745_midplane = { "C3745 Midplane", eeprom_c3745_midplane_data, sizeof(eeprom_c3745_midplane_data)/2,};/* ======================================================================== *//* Network Module Drivers *//* ======================================================================== */static struct c3745_nm_driver *nm_drivers[] = { &dev_c3745_nm_1fe_tx_driver, &dev_c3745_nm_16esw_driver, &dev_c3745_gt96100_fe_driver, &dev_c3745_nm_4t_driver, NULL,};/* ======================================================================== *//* Cisco 3745 router instances *//* ======================================================================== *//* Directly extract the configuration from the NVRAM device */ssize_t c3745_nvram_extract_config(vm_instance_t *vm,char **buffer){ u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr; m_uint32_t start,nvlen; m_uint16_t magic1,magic2; struct vdevice *nvram_dev; off_t nvram_size; int fd; if ((nvram_dev = dev_get_by_name(vm,"rom"))) dev_sync(nvram_dev); fd = vm_mmap_open_file(vm,"rom",&base_ptr,&nvram_size); if (fd == -1) return(-1); ios_ptr = base_ptr + C3745_NVRAM_OFFSET; end_ptr = base_ptr + nvram_size; if ((ios_ptr + 0x30) >= end_ptr) { vm_error(vm,"NVRAM file too small\n"); return(-1); } magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06)); magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08)); if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) { vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n", magic1,magic2); return(-1); } start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1; nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18)); if (!(*buffer = malloc(nvlen+1))) { vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen); return(-1); } cfg_ptr = ios_ptr + start + 0x08; if ((cfg_ptr + nvlen) > end_ptr) { vm_error(vm,"NVRAM file too small\n"); return(-1); } memcpy(*buffer,cfg_ptr,nvlen-1); (*buffer)[nvlen-1] = 0; return(nvlen-1);}static int c3745_nvram_push_config_part(vm_instance_t *vm, char *buffer,size_t len, u_char *ios_ptr){ m_uint32_t cfg_offset,cklen,tmp; m_uint16_t cksum; u_char *cfg_ptr; cfg_offset = 0x2c; cfg_ptr = ios_ptr + cfg_offset; /* Write IOS tag, uncompressed config... */ *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04); /* Store file contents to NVRAM */ memcpy(cfg_ptr,buffer,len); /* Write config addresses + size */ tmp = cfg_offset - 0x08; *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp); *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len); *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len); /* Compute the checksum */ cklen = C3745_NVRAM_SIZE - 0x08; cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum); return(0);}/* Directly push the IOS configuration to the NVRAM device */int c3745_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len){ u_char *base_ptr,*ios_ptr; int fd; fd = vm_mmap_create_file(vm,"rom",vm->rom_size*1048576,&base_ptr); if (fd == -1) return(-1); ios_ptr = base_ptr + C3745_NVRAM_OFFSET; /* Normal config */ c3745_nvram_push_config_part(vm,buffer,len,ios_ptr); /* Backup config */ c3745_nvram_push_config_part(vm,buffer,len,ios_ptr + C3745_NVRAM_SIZE); vm_mmap_close_file(fd,base_ptr,vm->rom_size*1048576); return(0);}/* Check for empty config */int c3745_nvram_check_empty_config(vm_instance_t *vm){ struct vdevice *rom_dev; m_uint64_t addr; size_t len; if (!(rom_dev = dev_get_by_name(vm,"rom"))) return(-1); addr = rom_dev->phys_addr + C3745_NVRAM_OFFSET; len = C3745_NVRAM_SIZE; while(len > 0) { if (physmem_copy_u32_from_vm(vm,addr) != 0) return(0); addr += sizeof(m_uint32_t); len -= sizeof(m_uint32_t); } /* Empty NVRAM */ vm->conf_reg |= 0x0040; printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg); return(0);}/* Create a new router instance */c3745_t *c3745_create_instance(char *name,int instance_id){ c3745_t *router; if (!(router = malloc(sizeof(*router)))) { fprintf(stderr,"C3745 '%s': Unable to create new instance!\n",name); return NULL; } memset(router,0,sizeof(*router)); if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C3745))) { fprintf(stderr,"C3745 '%s': unable to create VM instance!\n",name); goto err_vm; } c3745_init_defaults(router); router->vm->hw_data = router; return router; err_vm: free(router); return NULL;}/* Free resources used by a router instance */static int c3745_free_instance(void *data,void *arg){ vm_instance_t *vm = data; c3745_t *router; int i; if (vm->type == VM_TYPE_C3745) { router = VM_C3745(vm); /* Stop all CPUs */ if (vm->cpu_group != NULL) { vm_stop(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(FALSE); } } /* Remove NIO bindings */ for(i=0;i<C3745_MAX_NM_BAYS;i++) c3745_nm_remove_all_nio_bindings(router,i); /* Shutdown all Network Modules */ c3745_nm_shutdown_all(router); /* Free mainboard EEPROM */ for(i=0;i<3;i++) cisco_eeprom_free(&router->sys_eeprom[i]); /* Free all resources used by VM */ vm_free(vm); /* Free the router structure */ free(router); return(TRUE); } return(FALSE);}/* Delete a router instance */int c3745_delete_instance(char *name){ return(registry_delete_if_unused(name,OBJ_TYPE_VM, c3745_free_instance,NULL));}/* Delete all router instances */int c3745_delete_all_instances(void){ return(registry_delete_type(OBJ_TYPE_VM,c3745_free_instance,NULL));}/* Save configuration of a C3745 instance */void c3745_save_config(c3745_t *router,FILE *fd){ vm_instance_t *vm = router->vm; struct c3745_nio_binding *nb; struct c3745_nm_bay *bay; int i; /* General settings */ fprintf(fd,"c3745 create %s %u\n",vm->name,vm->instance_id); /* VM configuration */ vm_save_config(vm,fd); /* Network Module settings */ for(i=0;i<C3745_MAX_NM_BAYS;i++) { if (!(bay = c3745_nm_get_info(router,i))) continue; if (bay->dev_type) { fprintf(fd,"c3745 add_nm_binding %s %u %s\n", vm->name,i,bay->dev_type); } for(nb=bay->nio_list;nb;nb=nb->next) { fprintf(fd,"c3745 add_nio_binding %s %u %u %s\n", vm->name,i,nb->port_id,nb->nio->name); } } fprintf(fd,"\n");}/* Save configurations of all C3745 instances */static void c3745_reg_save_config(registry_entry_t *entry,void *opt,int *err){ vm_instance_t *vm = entry->data; c3745_t *router = VM_C3745(vm); if (vm->type == VM_TYPE_C3745) c3745_save_config(router,(FILE *)opt);}void c3745_save_config_all(FILE *fd){ registry_foreach_type(OBJ_TYPE_VM,c3745_reg_save_config,fd,NULL);}/* Set NM EEPROM definition */int c3745_nm_set_eeprom(c3745_t *router,u_int nm_bay, const struct cisco_eeprom *eeprom){ if (!nm_bay || (nm_bay >= C3745_MAX_NM_BAYS)) { vm_error(router->vm,"c3745_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay); return(-1); } if (cisco_eeprom_copy(&router->nm_bay[nm_bay].eeprom,eeprom) == -1) { vm_error(router->vm,"c3745_nm_set_eeprom: no memory.\n"); return(-1); } return(0);}/* Unset NM EEPROM definition (empty bay) */int c3745_nm_unset_eeprom(c3745_t *router,u_int nm_bay){ if (!nm_bay || (nm_bay >= C3745_MAX_NM_BAYS)) { vm_error(router->vm,"c3745_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay); return(-1); } cisco_eeprom_free(&router->nm_bay[nm_bay].eeprom); return(0);}/* Check if a bay has a port adapter */int c3745_nm_check_eeprom(c3745_t *router,u_int nm_bay){ if (!nm_bay || (nm_bay >= C3745_MAX_NM_BAYS)) return(FALSE); return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom));}/* Get bay info */struct c3745_nm_bay *c3745_nm_get_info(c3745_t *router,u_int nm_bay){ if (nm_bay >= C3745_MAX_NM_BAYS) return NULL; return(&router->nm_bay[nm_bay]);}/* Get NM type */char *c3745_nm_get_type(c3745_t *router,u_int nm_bay){ struct c3745_nm_bay *bay; bay = c3745_nm_get_info(router,nm_bay); return((bay != NULL) ? bay->dev_type : NULL);}/* Get driver info about the specified slot */void *c3745_nm_get_drvinfo(c3745_t *router,u_int nm_bay){ struct c3745_nm_bay *bay; bay = c3745_nm_get_info(router,nm_bay); return((bay != NULL) ? bay->drv_info : NULL);}/* Set driver info for the specified slot */int c3745_nm_set_drvinfo(c3745_t *router,u_int nm_bay,void *drv_info){ struct c3745_nm_bay *bay; if (!(bay = c3745_nm_get_info(router,nm_bay))) return(-1); bay->drv_info = drv_info; return(0);}/* Get a NM driver */static struct c3745_nm_driver *c3745_nm_get_driver(char *dev_type){ int i; for(i=0;nm_drivers[i];i++) if (!strcmp(nm_drivers[i]->dev_type,dev_type)) return nm_drivers[i]; return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -