u-boot第二阶段代码(仅启动linux)

主函数文件main.c

/*
  *文件名:  main.c
  *作者:  李炼
  *时间: 2014.07.22
  *功能:u-boot第二阶段代码,引导linux启动
*/
#include "main.h"
#include "type.h"
#include "common.h"
#include "setup.h"

//static int is_auto_run_cmd;
static struct tag *params;        //全局参数存放结构体

void dara_main(void)
{

	/* 浜伅 */
       int i;
       GPBCON = 0x0157ff;
       GPBDAT = 0x0000;                     /* 0xF0 CLOSE LED */
	/*0、设置串口*/
	ini_uart();
	uart_put_char('a');                      //单个字符输出测试
	uart_put_char('b');			
	puts("\r\n");						//回车换行
	print_tag();					 //字符串输出

	void (*theKernel)(int zero, int arch, unsigned int params);   //存放真正内核的第一个函数
        volatile unsigned int *p = (volatile unsigned int *)0x30008000;
       /*1、从NAND读内核到SDRAM*/
	printf("Copy kernel from nand flash \r\n");
	nand_read_ll_lp(0x30008000,0x00200000,0x00300000);
	//puthex(0x1234ABCD);
	//puts("\n\r");	
	//puthex(*p);
	//puts("\n\r");

	/*2、设置参数*/
	printf("Setup boot params \r\n");
	setup_start_tag ();
	setup_memory_tags ();
	setup_commandline_tag ("noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0");
	setup_end_tag ();
	
	/*3、跳转执行*/
	printf("Boot Kernel...\r\n");
	theKernel = (void (*)(int, int,unsigned int))0x30008000;
	theKernel(0,168,0x30000100);           
	/*
	  * mov r0,#0
	  * ldr   r1, =168       	//TQ2440对应机器码168
	  * ldr   r2, =0x30000100        //全局参数的存放起始地址
	  * mov pc,#0x30008000
        */
         printf("Error!\n\r");
	 /*程序无异常,不会到达此处*/
         //return -1;
}

void  setup_start_tag(void)
{
	params = (struct tag *)0x30000100;

	params->hdr.tag = ATAG_CORE;
	params->hdr.size = tag_size (tag_core);

	params->u.core.flags = 0;
	params->u.core.pagesize = 0;
	params->u.core.rootdev = 0;

	params = tag_next (params);
}
void  setup_memory_tags(void)
{
	
	params->hdr.tag = ATAG_MEM;
	params->hdr.size = tag_size (tag_mem32);

	params->u.mem.start =0x30000000;
	params->u.mem.size = 64*1024*1024;

	params = tag_next (params);
	
}

int stringlen(char * str)
{
	int i=0;
	while(str[i])
	{
              i++;
	}
	return i;
}

void stringcpy(char *dest,char *src)
{
	char *tmp = dest;

	while ((*dest++ = *src++) != '\0');

}


void setup_commandline_tag(char *cmdline)
{
	int len = stringlen(cmdline) + 1; 
	
	params->hdr.tag = ATAG_CMDLINE;
	params->hdr.size =
		(sizeof (struct tag_header) + len+3) >> 2;

	stringcpy (params->u.cmdline.cmdline, cmdline);

	params = tag_next(params);
}
void  setup_end_tag(void)
{
	params->hdr.tag = ATAG_NONE;
	params->hdr.size = 0;
}
/*
void puthex(unsigned int val)
{
 	int i;
 	int j;
	puts("0x");
	
	for(i=0;i<8;i++)
	{
		j = (val >> ((7-i)*4)) &0xf;
		if((j >= 0) && (j <= 9))
			uart_put_char('0' + j);
		else	
			uart_put_char('A' + j - 0xa);  
   		
	}
}
*/
void ini_uart(void)
{
	int i;
	
    	GPHCON = 0x00faaa;
    	GPHUP  = 0x7ff;
	for(i=0;i<100;i++);

    	UFCON0 = 0x0;  /*FIFO disable*/
    	UMCON0 = 0x0;  /* 绂佺敤AFC妯″紡 */
    	ULCON0 = 0x03; /* 鏅€氭ā寮?鏃犳牎楠屼綅,1涓仠姝綅,8浣嶅抚 */
    	UCON0  = 0x245; /* 寰堝璁剧疆...娉㈢壒鐜囦娇鐢ㄧ殑鏃堕挓婧愭槸PCLK */
    	UBRDIV0 = ((long)(50000000 / 16./115200+0.5) - 1); /* Baud-Rate */
	for(i=0;i<100;i++);
}

void delay(int value)
{
    volatile int j=0;
    while(j++ < value)
    {
        volatile int i=0x1FFFF;
        while(i--);
    }
}

void uart_put_char(u8 c)
{    
    int i;

    while(!(UTRSTAT0 & 0x2));
    UTXH0 = c;
    
}

u8 uart_get_char(void)
{
    while(!(UTRSTAT0 & 0x1));
    return URXH0;
}   

void puts(u8 *str)
{    
     int i;
    while(*str)
    {
        uart_put_char(*str++);
    }
}

#if 0
void gets(char *str)
{
    volatile unsigned char tmp_char;
    volatile char *tmp_buff = str;
    while((tmp_char = uart_get_char()))
	{
        if(is_auto_run_cmd)
		{
            	is_auto_run_cmd = 0;
            	printf("\r\ns3c2440 # ");
        	}
        switch(tmp_char)
		{
            case 0x7F:    //delete
                backspace:
			    if(tmp_buff > str)
				{
                    		tmp_buff--;
                    		uart_put_char(0x08);  //退格
                    		uart_put_char(0x1B);  //escape 溢出
                    		uart_put_char(0x5B);  //"["
                    		uart_put_char(0x4A);  //'J'
                }
                break;
            case 0x08:
                goto backspace;
                break;
	        case 0x0D:
                goto gets_finish;
                break;
            case 0x1B:
                uart_get_char();
                char dire = uart_get_char();
                break;
            default:
		        uart_put_char(tmp_char);
                *tmp_buff++ = tmp_char;
               break;
        }
    }
    gets_finish:
    *tmp_buff = 0;
}
#endif
void print_tag(void)
{
    printf("************************************************************\r\n");
    printf("*                                                          *\r\n");
    printf("*                     Hello World !                        *\r\n");
    printf("*                   writer :Li Lian                        *\r\n");
    printf("*                   date :2014.07.22                       *\r\n");
    printf("*                                                          *\r\n");
    printf("************************************************************\r\n");
}


 

文件setup.h

/*
 *  linux/include/asm/setup.h
 *
 *  Copyright (C) 1997-1999 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Structure passed to kernel to tell it about the
 *  hardware it's running on.  See linux/Documentation/arm/Setup
 *  for more info.
 *
 * NOTE:
 *  This file contains two ways to pass information from the boot
 *  loader to the kernel. The old struct param_struct is deprecated,
 *  but it will be kept in the kernel for 5 years from now
 *  (2001). This will allow boot loaders to convert to the new struct
 *  tag way.
 */
#ifndef __ASMARM_SETUP_H
#define __ASMARM_SETUP_H

/*
 * Usage:
 *  - do not go blindly adding fields, add them at the end
 *  - when adding fields, don't rely on the address until
 *    a patch from me has been released
 *  - unused fields should be zero (for future expansion)
 *  - this structure is relatively short-lived - only
 *    guaranteed to contain useful data in setup_arch()
 */
#define COMMAND_LINE_SIZE 1024

/* 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];
};


/*
 * The new way of passing information: a list of tagged entries
 */

/* The list ends with an ATAG_NONE node. */
#define ATAG_NONE	0x00000000

struct tag_header {
	u32 size;
	u32 tag;
};

/* The list must start with an ATAG_CORE node */
#define ATAG_CORE	0x54410001

struct tag_core {
	u32 flags;		/* bit 0 = read-only */
	u32 pagesize;
	u32 rootdev;
};

/* it is allowed to have multiple ATAG_MEM nodes */
#define ATAG_MEM	0x54410002

struct tag_mem32 {
	u32	size;
	u32	start;	/* physical start address */
};

/* VGA text type displays */
#define ATAG_VIDEOTEXT	0x54410003

struct tag_videotext {
	u8		x;
	u8		y;
	u16		video_page;
	u8		video_mode;
	u8		video_cols;
	u16		video_ega_bx;
	u8		video_lines;
	u8		video_isvga;
	u16		video_points;
};

/* describes how the ramdisk will be used in kernel */
#define ATAG_RAMDISK	0x54410004

struct tag_ramdisk {
	u32 flags;	/* bit 0 = load, bit 1 = prompt */
	u32 size;	/* decompressed ramdisk size in _kilo_ bytes */
	u32 start;	/* starting block of floppy-based RAM disk image */
};

/* describes where the compressed ramdisk image lives (virtual address) */
/*
 * this one accidentally used virtual addresses - as such,
 * its depreciated.
 */
#define ATAG_INITRD	0x54410005

/* describes where the compressed ramdisk image lives (physical address) */
#define ATAG_INITRD2	0x54420005

struct tag_initrd {
	u32 start;	/* physical start address */
	u32 size;	/* size of compressed ramdisk image in bytes */
};

/* board serial number. "64 bits should be enough for everybody" */
#define ATAG_SERIAL	0x54410006

struct tag_serialnr {
	u32 low;
	u32 high;
};

/* board revision */
#define ATAG_REVISION	0x54410007

struct tag_revision {
	u32 rev;
};

/* initial values for vesafb-type framebuffers. see struct screen_info
 * in include/linux/tty.h
 */
#define ATAG_VIDEOLFB	0x54410008

struct tag_videolfb {
	u16		lfb_width;
	u16		lfb_height;
	u16		lfb_depth;
	u16		lfb_linelength;
	u32		lfb_base;
	u32		lfb_size;
	u8		red_size;
	u8		red_pos;
	u8		green_size;
	u8		green_pos;
	u8		blue_size;
	u8		blue_pos;
	u8		rsvd_size;
	u8		rsvd_pos;
};

/* command line: \0 terminated string */
#define ATAG_CMDLINE	0x54410009

struct tag_cmdline {
	char	cmdline[1];	/* this is the minimum size */
};

/* acorn RiscPC specific information */
#define ATAG_ACORN	0x41000101

struct tag_acorn {
	u32 memc_control_reg;
	u32 vram_pages;
	u8 sounddefault;
	u8 adfsdrives;
};

/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
#define ATAG_MEMCLK	0x41000402

struct tag_memclk {
	u32 fmemclk;
};

struct tag {
	struct tag_header hdr;
	union {
		struct tag_core		core;
		struct tag_mem32	mem;
		struct tag_videotext	videotext;
		struct tag_ramdisk	ramdisk;
		struct tag_initrd	initrd;
		struct tag_serialnr	serialnr;
		struct tag_revision	revision;
		struct tag_videolfb	videolfb;
		struct tag_cmdline	cmdline;

		/*
		 * Acorn specific
		 */
		struct tag_acorn	acorn;

		/*
		 * DC21285 specific
		 */
		struct tag_memclk	memclk;
	} u;
};

struct tagtable {
	u32 tag;
	int (*parse)(const struct tag *);
};

#define __tag __attribute__((unused, __section__(".taglist")))
#define __tagtable(tag, fn) \
static struct tagtable __tagtable_##fn __tag = { tag, fn }

#define tag_member_present(tag,member)				\
	((unsigned long)(&((struct tag *)0L)->member + 1)	\
		<= (tag)->hdr.size * 4)

#define tag_next(t)	((struct tag *)((u32 *)(t) + (t)->hdr.size))
#define tag_size(type)	((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

#define for_each_tag(t,base)		\
	for (t = base; t->hdr.size; t = tag_next(t))

/*
 * Memory map description
 */
#define NR_BANKS 8

struct meminfo {
	int nr_banks;
	unsigned long end;
	struct {
		unsigned long start;
		unsigned long size;
		int           node;
	} bank[NR_BANKS];
};

extern struct meminfo meminfo;

#endif

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值