📄 boot_kernel.c
字号:
/* * vivi/kernel/boot-kernel.c: * copy the kernel image to ram, then execute it * * Author: Janghoon Lyu * Created: December 23, 2001 * Copyright: MIZI Resarch, Inc. All rights reserved. * * Last modified: $Date: 2004/04/19 04:00:29 $ * $Revision: 1.20 $ */#include <config.h>#include <machine.h>#include <memory.h>#include <boot_kernel.h>#include <param.h>#include <mtd/mtd.h>#include <mtd/partitions.h>#include <command.h>#include <vstring.h>#include <mmu.h>#include <types.h>#include <setup.h>#include <string.h>#include <serial.h>#include <irq.h>#include <processor.h>#define LINUX_KERNEL_OFFSET (0x8000)#define LINUX_PARAM_OFFSET (0x100)#define LINUX_PAGE_SIZE (SZ_4K)#define LINUX_PAGE_SHIFT (12)#define LINUX_ZIMAGE_MAGIC (0x016f2818)/* * Function: call_linux() * * Purpose: Execute the kernel * * Arguments: r0 - must contain a zero or else the kernel loops * r1 - architecture type * r2 - address to be executed * * Return: None * * Notes: This fucntion depends on the processor. */#ifdef CONFIG_ARCH_S3C2400void call_linux(long a0, long a1, long a2){ cache_clean_invalidate(); tlb_invalidate();__asm__( "mov r0, %0\n" "mov r1, %1\n" "mov r2, %2\n" "mov ip, #0\n" "mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */ "mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */ "mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */ "mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */ "mrc p15, 0, ip, c1, c0, 0\n" /* get control register */ "bic ip, ip, #0x0001\n" /* disable MMU */ "mcr p15, 0, ip, c1, c0, 0\n" /* write control register */ "mov pc, r2\n" "nop\n" "nop\n" : /* no outputs */ : "r" (a0), "r" (a1), "r" (a2) );}#elif defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C2440) || defined(CONFIG_ARCH_MMSP2)void call_linux(long a0, long a1, long a2){ cache_clean_invalidate(); tlb_invalidate();__asm__( "mov r0, %0\n" "mov r1, %1\n" "mov r2, %2\n" "mov ip, #0\n" "mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */ "mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */ "mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */ "mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */ "mrc p15, 0, ip, c1, c0, 0\n" /* get control register */ "bic ip, ip, #0x0001\n" /* disable MMU */ "mcr p15, 0, ip, c1, c0, 0\n" /* write control register */ "mov pc, r2\n" "nop\n" "nop\n" : /* no outputs */ : "r" (a0), "r" (a1), "r" (a2) );}#elif defined(CONFIG_ARCH_SA1100)void call_linux(long r0, long r1, long r2){ __asm__(" mov r10, r1\n" " mov r11, r2\n" " mcr p15, 0, r0, c8, c7, 0\n" /* flush I and D TlB */ " mcr p15, 0, r0, c7, c10, 4\n" /* drain the write buffer */ " mov r3, #0x130\n" " mcr p15, 0, r3, c1, c0, 0\n" /* disable the MMU */ /* make sure the pipeline is emptied */ " mov r0, #0\n" " mov r0, r0\n" " mov r0, r0\n" " mov r0, r0\n" " mov r0, r0\n" /* zero PID in Fast Context Switch Extension PID register */ " mov r0, #0\n" " mcr p15, 0, r0, c13, c0, 0\n" " mov r0, #0\n" " mov r1, r10\n" " mov pc, r11\n" /* jump to addr. bootloader is done */ : : "r" (r0), "r" (r1), "r" (r2) );}#elif defined(CONFIG_ARCH_PXA250)void call_linux(long r0, long r1, long r2){ __asm__(" mov r10, r1\n" " mov r11, r2\n" " mcr p15, 0, r0, c8, c7, 0\n" /* flush I and D TlB */ " mcr p15, 0, r0, c7, c10, 4\n" /* drain the write buffer */ " mov r3, #0x130\n" " mcr p15, 0, r3, c1, c0, 0\n" /* disable the MMU */ /* make sure the pipeline is emptied */ " mov r0, #0\n" " mov r0, r0\n" " mov r0, r0\n" " mov r0, r0\n" " mov r0, r0\n" /* zero PID in Fast Context Switch Extension PID register */ " mov r0, #0\n" " mcr p15, 0, r0, c13, c0, 0\n" " mov r0, #0\n" " mov r1, r10\n" " mov pc, r11\n" /* jump to addr. bootloader is done */ : : "r" (r0), "r" (r1), "r" (r2) );}#elif defined(CONFIG_ARCH_S3C24A0)void call_linux(long a0, long a1, long a2){ cache_clean_invalidate(); tlb_invalidate();__asm__( "mov r0, %0\n" "mov r1, %1\n" "mov r2, %2\n" "mov ip, #0\n" "mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */ "mrc p15, 0, ip, c1, c0, 0\n" /* get control register */ "bic ip, ip, #0x0001\n" /* disable MMU */ "mcr p15, 0, ip, c1, c0, 0\n" /* write control register */ "mov pc, r2\n" "nop\n" "nop\n" : /* no outputs */ : "r" (a0), "r" (a1), "r" (a2) );}#elif defined(CONFIG_ARCH_PXA27X)void call_linux(long r0, long r1, long r2){ __asm__(" mov r10, r1\n" " mov r11, r2\n" " mcr p15, 0, r0, c8, c7, 0\n" /* flush I and D TlB */ " mcr p15, 0, r0, c7, c10, 4\n" /* drain the write buffer */ " mov r3, #0x130\n" " mcr p15, 0, r3, c1, c0, 0\n" /* disable the MMU */ /* make sure the pipeline is emptied */ " mov r0, #0\n" " mov r0, r0\n" " mov r0, r0\n" " mov r0, r0\n" " mov r0, r0\n" /* zero PID in Fast Context Switch Extension PID register */ " mov r0, #0\n" " mcr p15, 0, r0, c13, c0, 0\n" " mov r0, #0\n" " mov r1, r10\n" " mov pc, r11\n" /* jump to addr. bootloader is done */ : : "r" (r0), "r" (r1), "r" (r2) );}#else#error not defined call_linux() for this architecture #endif/* * Function: setup_linux_param() * * Purpose: setup parameters for linux kernel. * * Arguments: param_base - base address of linux parameters * Normally, this address is RAM base address + 0x100. * * Return: None * * Notes: None */static void setup_linux_param(ulong param_base){ char *linux_cmd;#if 0 //phoenix20090212:blocked_compile error#ifdef CONFIG_KERNEL_VERSION_2_6 struct tag *tags = (struct tag *)param_base; linux_cmd = get_linux_cmd_line(); if (linux_cmd == NULL) { printk("There's no valid command line\n"); } tags->hdr.size = tag_size(tag_core); tags->hdr.tag = ATAG_CORE; tags->u.core.flags = 1; tags->u.core.pagesize = LINUX_PAGE_SIZE; tags->u.core.rootdev = 0xff; tags = tag_next(tags); tags->hdr.size = tag_size(tag_mem32); tags->hdr.tag = ATAG_MEM; tags->u.mem.size = DRAM_SIZE; tags->u.mem.start = DRAM_BASE; tags = tag_next(tags); tags->hdr.size = ((sizeof(struct tag_header) + 1024) >> 2); tags->hdr.tag = ATAG_CMDLINE; memcpy(tags->u.cmdline.cmdline, linux_cmd, 1024); printk("linux command line is: \"%s\"\n", tags->u.cmdline.cmdline); tags = tag_next(tags); tags->hdr.size = 0; tags->hdr.tag = ATAG_NONE;#else struct param_struct *params = (struct param_struct *)param_base; printk("Setup linux parameters at 0x%08lx\n", param_base); memset(params, 0, sizeof(struct param_struct)); /* 部坷苛 秦拎具 瞪 巴甸.. 抄叼啊 版氰利栏肺 措面 嘛篮 巴.. */ params->u1.s.page_size = LINUX_PAGE_SIZE; params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT); /* set linux command line */ linux_cmd = get_linux_cmd_line(); if (linux_cmd == NULL) { printk("There's no valid command line\n"); } else { memcpy(params->commandline, linux_cmd, strlen(linux_cmd)); printk("linux command line is: \"%s\"\n", params->commandline); }#endif#endif}static int media_type_is(const char *mt){ if (strncmp("ram", mt, 3) == 0) { return MT_RAM; } else if (strncmp("nor", mt, 3) == 0) { return MT_NOR_FLASH; } else if (strncmp("smc", mt, 3) == 0) { return MT_NAND_S3C24XX; } else if (strncmp("mdocp", mt, 4) == 0) { return MT_NAND_MDOCP; } else { return MT_UNKNOWN; }}static intcopy_kernel(u_char *buf, int mt){ int ret = 0; ulong zimage_magic; printk("copying kernel... "); switch (mt) { case MT_RAM: /* Noting to do */ ret = 0; break; case MT_NOR_FLASH: case MT_NAND_S3C24XX: case MT_NAND_MDOCP:#ifdef CONFIG_MTD if ((ret = mtd_read_part("kernel", buf, 0))) return ret; //nandll_read_blocks(0x30008000, 0x30000, 0xc0000);#endif break; case MT_UNKNOWN: default: ret = -2; } if (ret) { printk("fail\n"); if (ret == -2) printk("Undefined media type.\n"); } else { printk("ok\n"); } /* 府椽胶 目澄 捞固瘤啊 嘎绰瘤 埃窜洒 眉农. 酒聪搁 富备... */ memcpy((void *)&zimage_magic, buf + 36, sizeof(ulong)); if (zimage_magic != LINUX_ZIMAGE_MAGIC) printk("** WARNING: this binary is not compressed linux kernel image\n"); printk("zImage magic = 0x%08lx\n", zimage_magic); return ret;}/* * copy_initrd: copy ram disk to ram * * Arguments: * media_type: a typeof storage device * Return value: * 0: OK * others: Fail */static int copy_initrd(char *str){ int no; ulong addr[2]; /* 0 = offset to be write, 1 = length */ char *next; printk("copying initrd... "); no = 0; next = str; while((str = next) != NULL) { next = strchr(str, ','); if (next != NULL) { *next++ = '\0'; } addr[no] = simple_strtoul(str, NULL, 0); no++; } if (no != 2) { printk("wrong 'initrd' command\n"); return 1; }#ifdef CONFIG_MTD if (mtd_read_part("root", (u_char *)addr[0], addr[1])) printk("fail\n"); else printk("ok\n");#endif return 0;}/* * boot_kernel: booting the linux kernel * * from: address of stored kernel image * size: size of kernel image * media_type: a type of stoage device */int boot_kernel(int media_type){ char str[32]; ulong boot_mem_base = DRAM_BASE; ulong kernel_mem_base = boot_mem_base + LINUX_KERNEL_OFFSET; ulong mach_type; term_blank_on(); /* tern off terminal if you want */ /* copy kerne image */ copy_kernel((u_char *)(kernel_mem_base), media_type); /* copy initrd */ if (get_param_str("initrd", &str[0]) != NULL) { copy_initrd((char *)&str[0]); } /* Setup linux parameters and linux command line */ setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET); /* Get machine type */ get_param_ulong("mach_type", &mach_type); printk("MACH_TYPE = %d\n", mach_type); /* reset prcessor's resource */ reset_proc_res(); /* Go Go Go */ printk("NOW, Booting Linux......\n\n"); call_linux(0, mach_type, kernel_mem_base); return 0; /* never return */} /* * User Commands */static void display_help(void){ printk("Usage:\n"); printk(" boot -- booting kernel \n"); printk(" boot ram -- booting kernel using image on the ram\n"); printk(" boot help -- help about 'boot' command\n");}/* * default values: * kernel mtd partition = "kernel" * base adress of bootable memory = DRAM_BASE * media type = */void command_boot(int argc, const char **argv){ int media_type = 0; char m[16]; switch (argc) { case 1: if (get_param_str("media_type", m) == NULL) { printk("Unable to get media_type parameter\n"); return; } media_type = media_type_is(m); break; case 2: if (strncmp("help", argv[1], 4) == 0) { display_help(); return; } media_type = media_type_is(argv[1]); break; default: display_help(); break; } disable_irq_and_clear(); boot_kernel(media_type);}user_command_t boot_cmd = { "boot", command_boot, NULL};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -