Chinaunix首页 | 论坛 | 博客
  • 博客访问: 955493
  • 博文数量: 116
  • 博客积分: 3923
  • 博客等级: 中校
  • 技术积分: 1337
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 01:22
文章分类

全部博文(116)

文章存档

2013年(1)

2012年(17)

2011年(69)

2009年(29)

分类: LINUX

2009-04-28 01:22:42

project   : startup Linux in ViVi
struction : the code for startup Linux in ViVi.


(1) first, we look at the memory map as following chart:

--  _________________________________0x3400_0000 ( total: 64 M )
--  |  ViVi (1M)                |
--  |___________________________|____0x33F0_0000 ( ViViRAM_BASE)
--  |  Heap (1M)                |
--  |___________________________|____0x33E0_0000 ( Heap_BASE )
--  |  MMU Table (16K)          |
--  |___________________________|____0x33DF_C000 ( MMU_Table_BASE )
--  |  Priviate Data(16K x 3)   |
--  |___________________________|____0x33DF_0000 ( ViVi_Priv_RAM_BASE )
--  |  Stack (32K)              |  
--  |___________________________|____0x33DE_8000 ( STACK_BASE )
--  |                           |
--  |  61.90625 (M)             |
--  |                           |
--  |___________________________|____0x3000_0000 ( RAM_BASE )


vivi Priviate Data && Linux Command Line && MTD Param Arrange :

--  _______________________________0x33DF_C000 ( MMU_Table_BASE )
--  | Linux_cmd_line            |--> 16K linux cmd
--  |___________________________|__0x33DF_8000
--  |                           |
--  |                           |
--  | vivi_parameter_t []       |
--  |___________________________|____0x33DF_4016
--  | nb_params                 |--->number of params (8 bytes)
--  |___________________________|___ 0x33DF_4008
--  | "VIVIPARA"                |--->vivi_param_magic (8 bytes)
--  |___________________________|____0x33DF_4000 (VIVI PARAMETER TABLE)
--  |                           |
--  |                           |
--  | mtd_partiton []           |
--  |___________________________|____0x33DF_0016
--  | nb_mtd_parts              |--->number of mtd parts (8 bytes)
--  |___________________________|___ 0x33DF_0008
--  | "VIVIMTDP"                |--->mtd__part_magic (8 bytes)
--  |___________________________|____0x33DF_0000 (VIVI MTD PARAM)

Linux Kernel Starting ADDR && Startup Param &&

--  |___________________________|____0x33DE_8000 ( STACK_BASE )
--  |                           |
--  |                           |
--  |                           |
--  |                           |
--  |___________________________|_____0x3020_8000
--  |    Kernel Size             |
--  |                           |----> (2M bytes)
--  |___________________________|_____0x3000_8000 ( Linux kernel offset )
--  |  param_struct             |
--  | (as below struct)         |
--  |___________________________|____0x3000_0100 ( Linux startup Param )
--  |                           |
--  |___________________________|____0x3000_0000 ( RAM_BASE )


-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/* This is the old deprecated way to pass parameters to the kernel */
struct param_struct {
    union {
    struct {
     unsigned long page_size;           /* 0 */
     unsigned long nr_pages;            /* 4 */
     unsigned long ramdisk_size;        /* 8 */
     unsigned long flags;               /* 12 */
#define FLAG_READONLY    1
#define FLAG_RDLOAD    4
#define FLAG_RDPROMPT    8
     unsigned long rootdev;             /* 16 */
     unsigned long video_num_cols;      /* 20 */
     unsigned long video_num_rows;      /* 24 */
     unsigned long video_x;             /* 28 */
     unsigned long video_y;             /* 32 */
     unsigned long memc_control_reg;    /* 36 */
     unsigned char sounddefault;        /* 40 */
     unsigned char adfsdrives;          /* 41 */
     unsigned char bytes_per_char_h;    /* 42 */
     unsigned char bytes_per_char_v;    /* 43 */
     unsigned long pages_in_bank[4];    /* 44 */
     unsigned long pages_in_vram;       /* 60 */
     unsigned long initrd_start;        /* 64 */
     unsigned long initrd_size;         /* 68 */
     unsigned long rd_start;            /* 72 */
     unsigned long system_rev;          /* 76 */
     unsigned long system_serial_low;   /* 80 */
     unsigned long system_serial_high;  /* 84 */
     unsigned long mem_fclk_21285;      /* 88 */
    } s;
    char unused[256];
    } u1;
    union {
    char paths[8][128];
    struct {
     unsigned long magic;
     char n[1024 - sizeof(unsigned long)];
    } s;
    } u2;
    char commandline[COMMAND_LINE_SIZE];
};
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

(2) Code fragment for starup Linux_kernel in ViVi.

int boot_kernel(ulong from, size_t size, int media_type)
{
    int ret;
    ulong boot_mem_base;    /* base address of bootable memory*/
    ulong to;
    ulong mach_type;

    boot_mem_base = get_param_value("boot_mem_base", &ret);  // here boot_mem_base=0x3000_0000
    if (ret) {
        printk("Can't get base address of bootable memory\n");
        printk("Get default DRAM address. (0x%08lx\n", DRAM_BASE);
        boot_mem_base = DRAM_BASE;
    }

    /* copy kerne image */
    to = boot_mem_base + LINUX_KERNEL_OFFSET;   //here to=0x3000_8000
    printk("Copy linux kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ... ",
        from, to, size);
    ret = copy_kernel_img(to, (char *)from, size, media_type);  // "from" addr is the kernel area in nand flash
    if (ret) {
        printk("failed\n");
        return -1;
    } else {
        printk("done\n");
    }

    if (*(ulong *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) {    // Compressed or not
        printk("Warning: this binary is not compressed linux kernel image\n");
        printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
    } else {
        printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
    }

    /* Setup linux parameters and linux command line */
    setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET);  // see function setup_linux_param

    /* Get machine type */
    mach_type = get_param_value("mach_type", &ret); //see default_vivi_parameters[]
    printk("MACH_TYPE = %d\n", mach_type);

    /* Go Go Go */
    printk("NOW, Booting Linux......\n");
    call_linux(0, mach_type, to); //see function call_linux, r0=0; r1=mach_type; r2=to(here is linux kernel addr)

    return 0;    
}

vivi_parameter_t default_vivi_parameters[] = {
    { "mach_type",            MACH_TYPE,    NULL },
    { "media_type",            MT_S3C2440,    NULL },
    { "boot_mem_base",        0x30000000,    NULL },
    { "baudrate",            UART_BAUD_RATE,    NULL },
    { "xmodem",            1,        NULL },
    { "xmodem_one_nak",        0,        NULL },
    { "xmodem_initial_timeout",    300000,        NULL },
    { "xmodem_timeout",        1000000,    NULL },
    { "boot_delay",            0x1000000,    NULL }
};


static void setup_linux_param(ulong param_base)
{
    struct param_struct *params = (struct param_struct *)param_base;   // param_base=0x3000_0100
    char *linux_cmd;

    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;                // LINUX_PAGE_SIZE=4K
    params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT); // nr_pages: 0x4000=(64K >> 12)

    /* set linux command line */
    linux_cmd = get_linux_cmd_line(); // the command lied at 0x33DF_8000~0x33DF_C000 (16K)
    if (linux_cmd == NULL) {
        printk("Wrong magic: could not found linux command line\n");
    } else {
        memcpy(params->commandline, linux_cmd, strlen(linux_cmd) + 1);
        printk("linux command line is: \"%s\"\n", linux_cmd);
    }
}


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 outpus */
    : "r" (a0), "r" (a1), "r" (a2)
    );
}

阅读(1124) | 评论(0) | 转发(0) |
0

上一篇:Nand flash read in ViVi

下一篇:MMU Initial In ViVi

给主人留下些什么吧!~~