📄 main.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; /* NB: 酒流鳖瘤绰 MMU啊 波廉 乐澜. */ /* * Step 1: * 老窜 埃窜茄 硅呈窍唱 谎府绊.. */ 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. */ /* * Step 2: * Board甫 檬扁拳 钦聪促. */ 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(); } /* * Step 3: * 4G甫 府聪绢(linear)窍霸 概俏窍绊, 敲贰浆 皋葛府甫 * 盔窍绰 措肺 概俏窍绊, * MMU甫 难技夸. */ 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"); /* NB: 瘤陛何磐绰 MMU啊 悼累且 荐档 乐澜 */ /* * Now, vivi is running on the ram. MMU is enabled. */ /* * Step 4: * 何飘肺歹俊辑 悼利 皋葛府 且寸阑 荤侩且 荐 乐档废 */ /* initialize the heap area*/ ret = heap_init(); /*lib/heap.c*/ /*heap is a memory from which the functions 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(); } /* Step 5: * 磊, 困俊辑 皋葛府 概俏捞 力措肺 灯促搁, * MTD率阑 棱酒 壕矫促. * 悼矫俊, MTD狼 颇萍记partition 沥焊啊 乐促搁 * 棱酒郴摆烈. */ 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 struc (struct nand_chip *)(&mymtd[1]). */ /* Step 6: * 何飘肺歹甫 困茄 颇扼固磐 蔼甸阑 棱酒郴具摆烈. */ 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 + -