mips架构linux启动分析(四)(接收bios信息和环境初始化)

来源:互联网 发布:android程序员烂大街 编辑:程序博客网 时间:2024/06/08 16:50

老样子先看函数把.

void __init prom_init(void){//初始化命令prom_init_cmdline();//初始化环境prom_init_env();//这里所作的是把桥片进行了一些配置if (loongson_pch)loongson_pch->early_config();#ifdef CONFIG_NUMAprom_init_numa_memory();#elseprom_init_memory();#endif//初始化串口基地址信息prom_init_uart_base();#if defined(CONFIG_SMP)register_smp_ops(&loongson3_smp_ops);#endifboard_nmi_handler_setup = mips_nmi_setup;#ifdef CONFIG_CPU_LOONGSON3//这里是设置cpu的HT总线的窗口信息(也就是涉及到cpu的映射地址)if (!hw_coherentio) {/* set HT-access uncache */switch (cputype) {case Loongson_3A:HT_uncache_enable_reg0= 0xc0000000; //Low 256MHT_uncache_base_reg0= 0x0080fff0;HT_uncache_enable_reg1= 0xc0000000; //Node 0HT_uncache_base_reg1= 0x0000e000;HT_uncache_enable_reg2= 0xc0100000; //Node 1HT_uncache_base_reg2= 0x2000e000;HT_uncache_enable_reg3= 0xc0200000; //Node 2/3HT_uncache_base_reg3= 0x4000c000;writeq(0x0000202000000000, (void *)0x900000003ff02708);writeq(0xffffffe000000000, (void *)0x900000003ff02748);writeq(0x0000300000000086, (void *)0x900000003ff02788);break;default:break;}} printk("SET HT_DMA CACHED\n");}__sync();#endif /* CONFIG_CPU_LOONGSON3 */}

今天只分析函数    prom_init_cmdline();,    prom_init_env();

分别是接收bios传递的信息,和初始化环境

void __init prom_init_cmdline(void){int prom_argc;//记录参数的个数/* pmon passes arguments in 32bit pointers */int *_prom_argv; //记录参数的内容int i;long l;/* fw_arg0和fw_arg1在head.s文件中初始化,也就是记录了bios传递的参数 */prom_argc = fw_arg0;     //参数个数_prom_argv = (int *)fw_arg1;   //参数内容/*第一个参数为什么是g呢?因为pmon下载内核后运行的命令是g */arcs_cmdline[0] = '\0';  //第一个参数是g,所以吧第一个空出来for (i = 1; i < prom_argc; i++) {l = (long)_prom_argv[i];//判断参数有没有超过规定的长度if (strlen(arcs_cmdline) + strlen(((char *)l) + 1)    >= sizeof(arcs_cmdline))break;//strcat的作用就是合并两个字符串,在这里就是把参数内容放入到arcs_cmdline数组中,并且//参数之间由空格隔开strcat(arcs_cmdline, ((char *)l));strcat(arcs_cmdline, " ");}prom_init_machtype();}

初始化机器类型

#define MACHTYPE_LEN 50//系统定义的机器的类型static const char *system_types[] = {[MACH_LOONGSON_UNKNOWN]"unknown loongson machine",[MACH_LEMOTE_FL2E]"lemote-fuloong-2e-box",[MACH_LEMOTE_FL2F]"lemote-fuloong-2f-box",[MACH_LEMOTE_ML2F7]"lemote-mengloong-2f-7inches",[MACH_LEMOTE_YL2F89]"lemote-yeeloong-2f-8.9inches",[MACH_DEXXON_GDIUM2F10]"dexxon-gdium-2f",[MACH_LEMOTE_NAS]"lemote-nas-2f",[MACH_LEMOTE_LL2F]"lemote-lynloong-2f",[MACH_LOONGSON_GENERIC]"generic-loongson-machine",[MACH_LOONGSON_END]NULL,}; //初始化系统的机器类型void __init prom_init_machtype(void){char *p, str[MACHTYPE_LEN + 1];int machtype = MACH_LEMOTE_FL2E;  //默认的初始值mips_machtype = LOONGSON_MACHTYPE; //在板级setup文件中定义,初始时位unknow//在arcs_cmdline中查找有没有定义machtypep = strstr(arcs_cmdline, "machtype=");//没有传递就使用函数mach_prom_init_machtype初始化一下,一般是定义的if (!p) {mach_prom_init_machtype();return;}//查看参数machtype的长度p += strlen("machtype=");//把参数machtype拷贝到str中strncpy(str, p, MACHTYPE_LEN);str[MACHTYPE_LEN] = '\0';//查找str中有没有空格,如果由就用\0替换p = strstr(str, " ");if (p)*p = '\0';//在system_types中和bios传递过来的machtype对比,如果由匹配的就把mips_machtype设置成//对应的匹配值for (; system_types[machtype]; machtype++)if (strstr(system_types[machtype], str)) {mips_machtype = machtype;break;}}

prom_init_env环境初始化函数:

主要是:

1,解析bios传递过来的参数

2,初始化环境

先看一下封装参数的一些结构体,看不懂没关系,了解就行。

对应使用到的结构体,这些结构体都是BIOS传递过来的信息.
这些信息都是再bios中定义的,并封装了要传递给内核的信息。
目前我的平台上的这些信息是再bios中写死的,也就是说是人工把这些结构体初始化的。

----------------------------------------------------------------------struct boot_params{struct efi_loongson efi;struct efi_reset_system_t reset_system;};----------------------------------------------------------------------struct efi_loongson {u64 mps;/* MPS table */u64 acpi;/* ACPI table (IA64 ext 0.71) */u64 acpi20;/* ACPI table (ACPI 2.0) */struct smbios_tables smbios;/* SM BIOS table */u64 sal_systab;/* SAL system table */u64 boot_info;/* boot info table */};----------------------------------------------------------------------struct smbios_tables {u16 vers;     /* version of smbios */u64 vga_bios; /* vga_bios address */struct loongson_params lp;};----------------------------------------------------------------------struct loongson_params{u64 memory_offset;/* efi_memory_map_loongson struct offset */u64 cpu_offset;/* efi_cpuinfo_loongson struct offset */u64 system_offset;/* system_loongson struct offset */u64 irq_offset; /* irq_source_routing_table struct offset */u64 interface_offset;/* interface_info struct offset */u64 special_offset;    /*loongson_special_attribute struct offset*/u64 boarddev_table_offset;  /* board_devices offset */};----------------------------------------------------------------------struct efi_reset_system_t{u64 ResetCold;u64 ResetWarm;u64 ResetType;u64 Shutdown;u64 DoSuspend; /* NULL if not support */};----------------------------------------------------------------------struct efi_cpuinfo_loongson {u16 vers;     /* version of efi_cpuinfo_loongson */u32 processor_id; /* PRID, e.g. 6305, 6306 */enum loongson_cpu_type cputype; /* 3A, 3B, etc. */u32 total_node;   /* num of total numa nodes */u16 cpu_startup_core_id; /* Core id */u16 reserved_cores_mask;u32 cpu_clock_freq; /* cpu_clock */u32 nr_cpus;}__attribute__((packed));struct efi_cpuinfo_loongson *ecpu;enum loongson_cpu_type{Legacy_2E = 0x0,Legacy_2F = 0x1,Legacy_3A = 0x2,Legacy_3B = 0x3,Legacy_1A = 0x4,Legacy_1B = 0x5,Legacy_2G = 0x6,Legacy_2H = 0x7,Loongson_1A = 0x100,Loongson_1B = 0x101,Loongson_2E = 0x200,Loongson_2F = 0x201,Loongson_2G = 0x202,Loongson_2H = 0x203,Loongson_3A = 0x300,Loongson_3B = 0x301};----------------------------------------------------------------------struct efi_memory_map_loongson{u16 vers;/* version of efi_memory_map */u32 nr_map;/* number of memory_maps */u32 mem_freq;/* memory frequence */struct mem_map{u32 node_id;/* node_id which memory attached to */u32 mem_type;/* system memory, pci memory, pci io, etc. */u64 mem_start;/* memory map start address */u32 mem_size;/*each memory_map size, not the total size*/}map[LOONGSON3_BOOT_MEM_MAP_MAX];}__attribute__((packed));struct efi_memory_map_loongson *emap;----------------------------------------------------------------------#define MAX_UARTS 64struct uart_device {u32 iotype; /* see include/linux/serial_core.h */u32 uartclk;u32 int_offset;u64 uart_base;}__attribute__((packed));#define MAX_SENSORS 64#define SENSOR_TEMPER  0x00000001#define SENSOR_VOLTAGE 0x00000002#define SENSOR_FAN     0x00000004struct sensor_device {char name[32];  /* a formal name */char label[64]; /* a flexible description */u32 type;       /* SENSOR_* */u32 id;         /* instance id of a sensor-class */u32 fan_policy; /*see arch/mips/include/asm/mach-loongson/loongson_hwmon.h */u32 fan_percent;/* only for constant speed policy */u64 base_addr;  /* base address of device registers */}__attribute__((packed));struct system_loongson{u16 vers;     /* version of system_loongson */u32 ccnuma_smp; /* 0: no numa; 1: has numa */u32 sing_double_channel; /* 1:single; 2:double */u32 nr_uarts;struct uart_device uarts[MAX_UARTS];u32 nr_sensors;struct sensor_device sensors[MAX_SENSORS];char has_ec;char ec_name[32];u64 ec_base_addr;char has_tcm;char tcm_name[32];u64 tcm_base_addr;u64 workarounds; /* see workarounds.h */}__attribute__((packed));struct system_loongson *esys;----------------------------------------------------------------------#define MAX_RESOURCE_NUMBER 128struct resource_loongson {u64 start; /* resource start address */u64 end;   /* resource end address */char name[64];u32 flags;};struct board_devices{char name[64];    /* hold the device name */u32 num_resources; /* number of device_resource */struct resource_loongson resource[MAX_RESOURCE_NUMBER]; /* for each device's resource *//* arch specific additions */struct archdev_data archdata;};struct board_devices *eboard;----------------------------------------------------------------------struct irq_source_routing_table {u16 vers;u16 size;u16 rtr_bus;u16 rtr_devfn;u32 vendor;u32 device;u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */u64 ht_enable;  /* irqs used in this PIC */u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */u64 pci_mem_start_addr;u64 pci_mem_end_addr;u64 pci_io_start_addr;u64 pci_io_end_addr;u64 pci_config_addr;u16 dma_mask_bits;u16 dma_noncoherent;}__attribute__((packed));struct irq_source_routing_table *eirq_source;----------------------------------------------------------------------struct interface_info{u16 vers; /* version of the specificition */u16 size;u8  flag;char description[64];}__attribute__((packed));struct interface_info *einter;----------------------------------------------------------------------struct loongson_special_attribute{u16 vers;     /* version of this special */char special_name[64]; /* special_atribute_name */u32 loongson_special_type; /* type of special device */struct resource_loongson resource[MAX_RESOURCE_NUMBER]; /* for each device's resource */};struct loongson_special_attribute *especial;----------------------------------------------------------------------

void __init prom_init_env(void){/* pmon passes arguments in 32bit pointers */unsigned int processor_id;        char *bios_info;        char *board_info;int i;/* firmware arguments are initialized in head.S */boot_p = (struct boot_params *)fw_arg2;loongson_p = &(boot_p->efi.smbios.lp);//接收bios传递的信息,为解析做准备esys= (struct system_loongson *)((u64)loongson_p + loongson_p->system_offset);ecpu= (struct efi_cpuinfo_loongson *)((u64)loongson_p + loongson_p->cpu_offset);emap= (struct efi_memory_map_loongson *)((u64)loongson_p + loongson_p->memory_offset);eboard= (struct board_devices *)((u64)loongson_p + loongson_p->boarddev_table_offset);einter= (struct interface_info *)((u64)loongson_p + loongson_p->interface_offset);eirq_source = (struct irq_source_routing_table *)((u64)loongson_p + loongson_p->irq_offset);especial = (struct loongson_special_attribute *)((u64)loongson_p + loongson_p->special_offset);//根据cpu的类型,进行cpu一些特定的配置cputype = ecpu->cputype;switch (cputype) {case Loongson_3A:cores_per_node = 4;cores_per_package = 4;smp_group[0] = 0x900000003ff01000;smp_group[1] = 0x900010003ff01000;smp_group[2] = 0x900020003ff01000;smp_group[3] = 0x900030003ff01000;ht_control_base = 0x90000EFDFB000000;loongson_chipcfg[0] = 0x900000001fe00180;loongson_chipcfg[1] = 0x900010001fe00180;loongson_chipcfg[2] = 0x900020001fe00180;loongson_chipcfg[3] = 0x900030001fe00180;loongson_chiptemp[0] = 0x900000001fe0019c;loongson_chiptemp[1] = 0x900010001fe0019c;loongson_chiptemp[2] = 0x900020001fe0019c;loongson_chiptemp[3] = 0x900030001fe0019c;loongson_freqctrl[0] = 0x900000001fe001d0;loongson_freqctrl[1] = 0x900010001fe001d0;loongson_freqctrl[2] = 0x900020001fe001d0;loongson_freqctrl[3] = 0x900030001fe001d0;loongson_workarounds = WORKAROUND_CPUFREQ;break;default:cores_per_node = 1;cores_per_package = 1;loongson_chipcfg[0] = 0x900000001fe00180;}//确定cpu的核数nr_cpus_loongson = ecpu->nr_cpus;//确定cpu的频率cpu_clock_freq = ecpu->cpu_clock_freq;//确定cpu的启动核的idloongson_boot_cpu_id = ecpu->cpu_startup_core_id;loongson_reserved_cpus_mask = ecpu->reserved_cores_mask;#ifdef CONFIG_KEXEC//启动核的中断基地址loongson_boot_cpu_id = read_c0_ebase() & 0x3ff;for (i = 0; i < loongson_boot_cpu_id; i++)loongson_reserved_cpus_mask |= (1<<i);#endifif (nr_cpus_loongson > NR_CPUS || nr_cpus_loongson == 0)nr_cpus_loongson = NR_CPUS;nr_nodes_loongson = (nr_cpus_loongson + cores_per_node - 1) / cores_per_node;//pci_mem的开始和结束地址pci_mem_start_addr = eirq_source->pci_mem_start_addr;pci_mem_end_addr = eirq_source->pci_mem_end_addr;//pciio的基地址loongson_pciio_base = eirq_source->pci_io_start_addr;//DMA的掩码loongson_dma_mask_bits = eirq_source->dma_mask_bits;if (loongson_dma_mask_bits < 32 || loongson_dma_mask_bits > 64)loongson_dma_mask_bits = 32;//判断cpu是否具有dma硬件一致性 if (((read_c0_prid() & 0xf) == PRID_REV_LOONGSON3A_R2)|| ((read_c0_prid() & 0xf) == PRID_REV_LOONGSON3A_R3)) {eirq_source->dma_noncoherent = 1;}//根据启动时传递的参数,来配置是否使能dmah一致性 if (strstr(arcs_cmdline, "cached"))eirq_source->dma_noncoherent = 0;if (strstr(arcs_cmdline, "uncached"))eirq_source->dma_noncoherent = 1;if (strstr(arcs_cmdline, "hwmon"))loongson_hwmon = 1;elseloongson_hwmon = 0;hw_coherentio = !eirq_source->dma_noncoherent;//判断使用的桥片是2H还是rs780,这里使用的是2Hif (strstr(eboard->name,"2H")) {loongson_pch = &ls2h_pch;loongson_ec_sci_irq = 0x80;}else {loongson_pch = &rs780_pch;loongson_ec_sci_irq = 0x07;}//解析bios信息        /* parse bios info */        strcpy(_bios_info, einter->description);        bios_info = _bios_info;        bios_vendor = strsep(&bios_info, "-");        strsep(&bios_info, "-");        strsep(&bios_info, "-");        bios_release_date = strsep(&bios_info, "-");        if (!bios_release_date)                bios_release_date = especial->special_name;//解析板卡信息        /* parse board info */        strcpy(_board_info, eboard->name);        board_info = _board_info;        board_manufacturer = strsep(&board_info, "-");//解析poweroff,restart,suspend的地址信息poweroff_addr = boot_p->reset_system.Shutdown;restart_addr = boot_p->reset_system.ResetWarm;suspend_addr = boot_p->reset_system.DoSuspend;//vga地址vgabios_addr = boot_p->efi.smbios.vga_bios;//先把loongson_ecname清零,再给其赋值memset(loongson_ecname, 0, 32);if (esys->has_ec)memcpy(loongson_ecname, esys->ec_name, 32);loongson_workarounds |= esys->workarounds;//串口数loongson_nr_uarts = esys->nr_uarts;if (loongson_nr_uarts < 1 || loongson_nr_uarts > MAX_UARTS)loongson_nr_uarts = 1;//复制bios传递的串口信息到loongsin_uarts中memcpy(loongson_uarts, esys->uarts,sizeof(struct uart_device) * loongson_nr_uarts);//读取sensors的数量,并把bios传递过来的其信息复制到loongson_sensors中loongson_nr_sensors = esys->nr_sensors;if (loongson_nr_sensors > MAX_SENSORS)loongson_nr_sensors = 0;if (loongson_nr_sensors)memcpy(loongson_sensors, esys->sensors,sizeof(struct sensor_device) * loongson_nr_sensors);//根据cpu_id配置cpu的频率if (cpu_clock_freq == 0) {processor_id = (¤t_cpu_data)->processor_id;switch (processor_id & PRID_REV_MASK) {case PRID_REV_LOONGSON3A_R1:case PRID_REV_LOONGSON3A_R2:case PRID_REV_LOONGSON3A_R3:cpu_clock_freq = 900000000;break;default:cpu_clock_freq = 100000000;break;}}}