📄 main_edit.c
字号:
/* * vivi/main.c: main routine * * Copyright (C) 2001,2002 MIZI Research, Inc. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Author: Janghoon Lyu <nandy@mizi.com> * Date : $Date: 2002/08/28 06:00:11 $ * * $Revision: 1.7 $ * $Id: main.c,v 1.7 2002/08/28 06:00:11 nandy Exp $ * * * History * * 2001-10-xx: Janghoon Lyu <nandy@mizi.com> * - Initial code * * 2001-01-26: Janghoon Lyu <nandy@mizi.com> * - Release VIVI Bootloader * * 2002-07-02: Janghoon Lyu <nandy@mizi.com> * - bootldr狼 儡犁甫 没家窍搁辑 货酚霸 累己 */#include "config.h"#include "machine.h"#include "mmu.h"#include "heap.h"#include "serial.h"#include "printk.h"#include "command.h"#include "priv_data.h"#include "getcmd.h"#include "vivi_string.h"#include "mtd/mtd.h"#include "processor.h"#include <reset_handle.h>#include <types.h> extern char *vivi_banner;void vivi_shell(void){#ifdef CONFIG_SERIAL_TERM /*CONFIG_SERIAL_TERM=y*/ serial_term(); /*drivers/serial/term.c*/#else#error there is no terminal.#endif}void run_autoboot(void){/*defined at lib/boot_kernel.cuser_command_t boot_cmd = { "boot", command_boot, //defined at lib/boot_kernel.c NULL, "boot [{cmds}] \t\t\t-- Booting linux kernel"};*/ while (1) { exec_string("boot"); /*lib/command.c*/ printk("Failed 'boot' command. reentering vivi shell\n"); /* if default boot fails, drop into the shell */ vivi_shell(); }}static void error(void){ putstr("Sorry. We can not run vivi\n"); for (;;) /* nothing */; /* infinite loop */}#define DEFAULT_BOOT_DELAY 0x30000000void boot_or_vivi(void){ char c; int ret; ulong boot_delay;/*在include/priv_data.h中定义typedef struct parameter { char name[MAX_PARAM_NAME]; param_value_t value; void (*update_func)(param_value_t value);} vivi_parameter_t; *//*在arch/s3c2410/smdk.c中定义vivi_parameter_t default_vivi_parameters[] = { { "mach_type", MACH_TYPE, NULL }, { "media_type", MT_S3C2410, NULL }, { "boot_mem_base", 0x30000000, NULL }, { "baudrate", UART_BAUD_RATE, NULL }, { "xmodem_one_nak", 0, NULL }, { "xmodem_initial_timeout", 300000, NULL }, { "xmodem_timeout", 1000000, NULL }, { "ymodem_initial_timeout", 1500000, NULL }, { "boot_delay", 0x1000, NULL }};*/ boot_delay = get_param_value("boot_delay", &ret); /*lib/priv_data/param.c*/ if (ret) boot_delay = DEFAULT_BOOT_DELAY; /* If a value of boot_delay is zero, * unconditionally call vivi shell */ if (boot_delay == 0) vivi_shell(); /* * wait for a keystroke (or a button press if you want.) */ printk("Press Return to start the LINUX now, any other key for vivi\n"); c = awaitkey(boot_delay, NULL); /*drivers/serial/serial_core.c*/ if (((c != '\r') && (c != '\n') && (c != '\0'))) { printk("type \"help\" for help.\n"); vivi_shell(); } run_autoboot(); return;}/***************************************************************************************************what main do(this is the stage2 of bootloader):******************************************************************************************************/int main(int argc, char *argv[]){ int ret; putstr("\r\n"); putstr(vivi_banner); reset_handler(); /*lib/reset_handle.c */ /*it calls function clear_mem((unsigned long)USER_RAM_BASE, (unsigned long)USER_RAM_SIZE) in lib/memory.c*/ /*I can't find where USER_RAM_BASE and USER_RAM_SIZE were defined. */ ret = board_init(); /*arch/s3c2410/smdk.c*/ /*it calls init_time(at arch/s3c2410/proc.c) and set_gpios(in arch/s3c2410/smdk.c)*/ /*init_time: TCFG0 = 0 | 0xf00 | 0 */ if (ret) { putstr("Failed a board_init() procedure\r\n"); error(); } mem_map_init(); /*arch/s3c2410/mmu.c line194*/ /*1. call mem_map_nand_boot in arch/s3c2410/mmu.c this function call mem_mapping_linear immediately mem_mapping_linear(arch/s3c2410/mmu.c): initialize the mmu translation table, Make DRAM section cacheable 2. call cache_clean_invalidate in arch/s3c2410/mmu.c: clean and invalidate all cache lines 3. call tlb_invalidate in arch/s3c2410/mmu.c: invalidate I & D TLBs */ mmu_init(); /*arch/s3c2410/mmu.c line120*/ /*call arm920_setup in arch/s3c2410/mmu.c: 1. invalidate I,D caches 2. drain write buffer 3. invalidate I,D TLBs 4. load page table pointer(has been initialized at mmm_mapping_linear upside) 5. set MMU control registers: a. base location of exception = 0 (exception vectors' start address is 0x00000000) b. RS=0b00 (RS is not used as AP=0b11 which means all access types permitted in both supervisor and user mode) c. set little-endian d. mmu enable putstr("Succeed memory mapping.\r\n"); /* initialize the heap area*/ ret = heap_init(); /*lib/heap.c*/ /*heap is a memory from which the function mmalloc require a memory block it calls mmalloc_init in lib/heap.c to initialize the heap */ if (ret) { putstr("Failed initailizing heap region\r\n"); error(); } ret = mtd_dev_init(); /*drivers/mtd/mtdcore.c*/ /*it calls the functions mtd_init at drivers/mtd/maps/s3c2410_flash.c: calls smc_init at the same file: a. mmalloc memory for strcut mymtd b. initialize (struct nand_chip *)(&mymtd[1]) for NAND FLASH c. call smc_insert at the same file: call the functions smc_scan at drivers/mtd/nand/smc_core.c: read the ID of NAND FLASH, compare it with the pre-defined infomation of some usually types of NAND FLASH, and then set the NAND FLASH's data struct (struct nand_chip *)(&mymtd[1]). */ init_priv_data(); /*lib/priv_data/rw.c*/ /*there are two sets of vivi's parameters, one are the default parameters and the other are the saved parameters. init_priv_data load the default parameters on the memory, and then load the saved parameters and overwrite the corespointing part of the default parameters if the saved parameters is validate. The saved parameters were stored at the param partion of nand flash. 1. get_default_data(lib/priv_data/rw.c): a. get_default_param_tlb, defined at struct default_vivi_parameters at arch/s3c2410/smdk.c b. get_default_linux_cmd, copy linux command "char linux_cmd[] = "noinitrd root=/dev/mtdblock/0 init=/linuxrc console=ttyS0" "(arch/s3c2410/smdk.c) c. get_default_mtd_partition, defined at struct default_mtd_partitions at arch/s3c2410/smdk.c 2. load_saved_priv_data(lib/priv_data/rw.c): a. read_saved_priv_data_blk(at the same file), read the saved vivi parameters from the param part of nand flash to DRAM_BASE b. copy the saved tlb parameters from DRAM_BASE to overwrite what 1.a stores c. copy the saved linux command from DRAM_BASE to overwrite what 1.b stores d. copy the saved part parameters from DRAM_BASE to overwrite what 1.c stores */ /* Step 7: * 啊阐 荤捞(荤厩窍绊 捞惑茄)茄 焊靛甸阑 困秦辑 */ misc(); /*arch/s3c2410/smdk.c*/ /*call the function add_command(&cpu_cmd) defined at lib/command.c, to add the cpu command to the command chain this command is used to change the cpu's clock */ init_builtin_cmds(); /*lib/command.c*/ /*1. add_command(&bon_cmd) 2. add_command(&reset_cmd) 3. add_command(¶m_cmd) 4. add_command(&part_cmd) 5. add_command(&mem_cmd) 6. add_command(&load_cmd) 7. add_command(&go_cmd) 8. add_command(&dump_cmd) 9. add_command(&call_cmd) 10.add_command(&boot_cmd) 11.add_command(&help_cmd) */ /* Step 8: * 绢叼肺 哎鳖唱? */ boot_or_vivi(); /*call vivi_shell() or run_autoboot. 1. run_autoboot: exec_string("boot") (lib/command.c): parse the sting "boot", and then call the function execcmd: use the execcmd's parameter to find the boot_cmd's function and executive it: the boot_cmd was defined at lib/boot_kernel.c(see follow): user_command_t boot_cmd = { "boot", command_boot, NULL, "boot [{cmds}] \t\t\t-- Booting linux kernel" }; so, we call the function command_boot(lib/boot_kernel.c): a. media_type = get_param_value("media_type", &ret) (lib/priv_data/param.c), media_type=3 b. kernel_part = get_mtd_partition("kernel") (lib/priv_data/mtdpart.c), see also arch/s3c2410/smdk.c name: "kernel", offset: 0x00030000, size: 0x00100000, flag: 0 c. boot_kernel(from, size, media_type) (lib/boot_kernel.c): i. copy the kernel image from the kernel partion on nand flash to ram(boot_mem_base + LINUX_KERNEL_OFFSET, 0x30008000)using the copy_kernel_img. ii.setup_linux_param, set the linux parameters at boot_mem_base + LINUX_PARAM_OFFSET(0x30000100), these parameters were stored as a struct param_struct, which contains the command line parameter. iii.call_linux(0, mach_type, to) (boot_mem_base + LINUX_KERNEL_OFFSET=0x30008000) (1). cache_clean_invalidate (2). tlb_invalidate (3). use the inline asm to jump to linux kernel: define the p15 corprocessor: zero PID invalidate I,D caches drain write buffer invalidate I,D TLBs get control register disable MMU write control register set the PC register as the kernel address: mov pc, r2 2. vivi_shell: call the function serial_term at drivers/serial/term.c: a. printk("%s> ", prompt), display the string "vivi>" b. getcmd(cmd_buf, MAX_CMDBUF_SIZE) at drivers/serial/getcmd.c, wait for the command send from serial port by user c. exec_string(cmd_buf) at lib/command.c: parseargs execcmd *//*******************************************************************************************Now, the DRAM is seperated to these parts;+----------------------------------------------- + 0x33ff_ffff = 0x3000_0000+64M-1+ ++ ++ 1M VIVI ++ ++ ++-----------------------------------------------+ 0x33f0_0000 = VIVI_RAM_BASE+ ++ ++ 1M HEAP ++ ++ ++-----------------------------------------------+ 0x33e0_0000 = HEAP_BASE+ 16k MMU_TABLE ++-----------------------------------------------+ 0x33df_c000 = MMU_TABLE_BASE (used at the stage2 of bootloader)+ 16k LINUX_CMD ++ + LINUX_CMD_OFFSET = 16 k+ 16k PARAMETER_TLB ++ + PARAMETER_TLB_OFFSET = 16k+ 16k PARAMETER_PART ++-----------------------------------------------+ 0x33df_0000 = VIVI_PRIV_RAM_BASE (PARAMETER_PART_OFFSET = 0)+ ++ 32k STACK + + ++-----------------------------------------------+ 0x33de_8000 = STACK_BASE+ . ++ . ++ . ++ . ++ . ++ . ++-----------------------------------------------++ ++ ++ 1M LINUX KERNEL ++ ++ ++-----------------------------------------------+ 0x3000_8000 = the kernel image is placed begin this address+ ++ LINUX PAREMETER + +-----------------------------------------------+ LINUX_PARAM_OFFSET = 0x100+-----------------------------------------------+ 0x3000_0000 = RAM_BASE*******************************************************************************************/ /* 咯扁鳖瘤 坷搁 捞惑窍瘤夸. 弊犯瘤 臼唱夸? */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -